home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 1
/
Cream of the Crop 1.iso
/
COMM
/
MSKRMSRC.ARJ
/
MSGIBM.ASM
next >
Wrap
Assembly Source File
|
1991-10-24
|
168KB
|
5,157 lines
Name msgibm
; File MSGIBM.ASM
include mssdef.h
; Copyright (C) 1982,1991, Trustees of Columbia University in the
; City of New York. Permission is granted to any individual or
; institution to use, copy, or redistribute this software as long as
; it is not sold for profit and this copyright notice is retained.
; Tektronix emulator for use with MS Kermit/IBM.
; Edit history:
; 6 Sept 1991 version 3.11
; 2 March 1991 version 3.10
; Last edit 5 March 1991
; 12 Nov 1990 Add text cursor symbol, and on 17 Nov add cursor on/off.
; 2 Nov 1990 Add Microsoft mouse direct support.
; 8 June 1989 Added Wyse-700 support from Mikko Laanti.
; 21 Nov 1988 Version 2.32
; 1 Nov 1987 Heavy rewrite to integrate code into regular MS Kermit/IBM
; material. [jrd]
;==============================================================================
; Original version for TI Pro computers by
; 12-Dec-84 Joe Smith, CSM Computing Center, Golden CO 80401
; adapted to IBM PC June 1987 by Brian Holley,
; Faculty of Economics and Politics
; University of Cambridge, England
; Email: BJH6@UK.AC.CAM.PHX
; Upgraded and integrated into MS Kermit 2.30 by Joe Doupnik, Utah State Univ.
;
; Description of Tektronix commands
;
; ESC CONTROL-E (ENQ) requests a status report
; ESC FORMFEED erases the screen.
; ESC CONTROL-X turns on bypass mode (ignore incoming characters).
; ESC CONTROL-Z turns on the crosshairs (not on 4006 or 4025)
; ESC 2 exit Tek submode for text mode (ignore if doing full Tek)
; ESC ? is replaced by DEL code, to assist line plots with 7 bit systems.
; ESC [ Pn ; Pn m set screen colors. Pn = 30 + sum of colors for foregnd,
; 40 + sum of colors for background, Pn = 0 sets b/w, Pn = 1 for high
; intensity. Colors are red = 1, green = 2, blue = 4.
; ESC [ ? 3 8 l exits Tek mode and returns to host text terminal type
; (VT102 if none defined yet). This is an extension from DEC VT340's.
; ESC [ ? 256 n invokes a screen size report, for Word Perfect. Report is
; ESC [ ? 256; height; width; num colors n where num colors is 0, 1 or
; 16; report ESC [ ? 24; 80; 0 n for pure text mono systems.
; ESC @ through ESC M sets default fill pattern as below (1=@...).
; ESC Z report terminal type (as VT320)
; ESC [ 2; 2 $ u host request color palette report.
; ESC / xhome;yhome;xwidth;yheight x draw an empty rectangle
; ESC / xhome;yhome;xwidth;yheight;pattern y fill rectangle with pattern
; ESC / xhome;yhome;xwidth;yheight;pattern z fill rect with pattern+border
; where x/yhome is the lower left Tek corner, xwidth and yheight are the
; Tek width and height. All values are decimal numbers.
; Patterns 0:use default, 1:solid, 2:grey, 3:left to right slant, 4:right to
; left slant, 5:horizontal lines, 6:vertical lines, 7:slanted cross-hatch,
; 8:vertical cross-hatch, 9:checkerboard; 10:dotted, 11:horiz herringbone,
; 12:vertical herringbone,13 and above:border without fill. All are tiling
; 8x8 pixel patterns.
; ESC / param a, ... ESC / param c set user definable line drawing pattern
; to 16 bit value of param; plot as lsb first.
; ESC / 2 h or l, ESC / 9 h or l. h is set, l is reset, 2 is destructive
; space and 9 is destructive backspace. Defaults are reset.
; ESC x ESC y ESC z selects one of these user definable patterns above.
; ESC P P1; P2; P3 q string ESC \ a Sixel Graphics command
; P1 and P3 ignored, P2 = 0 or 2 means draw 0 bits in background, 1 means
; skip them.
; string is
; sixel chars (3fh..7eh, lower 6 bits+3fh, displayed lsb at the top)
; ! Pn sixel char where Pn is a repeat count
; " Pan; Pad; Ph; Pv raster attributes (all ignored for now)
; # Pc; Pu; Px; Py; Pz coloring as follows
; Pc is color palette, 0-255 (note, only 0..15 are predefined)
; Pu is color units, 1=HLS, 2=RGB
; For Hue Lightness Saturation:
; Px = Hue angle, 0-360 degrees. The colors are mapped around
; the color wheel in 60 degree segments as Hues:
; 0-29 deg = blue, 30-89 = magenta (blue + red), 90-149 = red,
; 150-209 = yellow (red + green), 210-269 = green,
; 270-329 = cyan (green + blue), 330-359 = blue.
; Py = Lightness, 0-100%, Pz = Saturation, 0-100%
; Lightness Sat = 51-100 Sat = 11-50 Sat = 0-10
; 86-100 bold white bold white bold white
; 71-85 bold hue bold white bold white
; 57-70 bold hue grey (dim white) grey
; 43-56 bold hue dim hue black
; 29-42 dim hue grey grey
; 14-28 dim hue black black
; 0-13 black black black
; Note that Py = Pz = 50 gives the widest spectrum.
; For RGB: Px = red, 0-100%, Py = green, 0-100%, Pz = blue, 0-100%
; If any color exceeds 50% then the bold bit is turned on for
; the ensemble (IBM ega display adapter constraint for RGBi).
;
; Palette registers can be selected by the substring
; # Pc followed by a non-numeric char other than ";"
; and Pc is the palette register, 0-255.
;
; $ (dollar sign ) meaning go to left margin
; - (minus) meaning go to left margin 6 dots down.
; This command yields one or more sets of 6 vertically arranged dots. They
; are placed starting at the top and left side of the current text cell.
; Escape sequences are permitted within string and occur without disruption.
; CONTROL-] (GS) turns on plot mode, the first move will be with beam off.
; CONTROL-^ (RS) turns on incremental plot mode. RS space means move pen up
; RS P means move pen down, following letters: A, E, D, F, B, J, H, I mean
; move right, right and up, up, left and up, left, left and down, down, and
; right and down, respectively. Ex: RS <space> J J J means move three Tek
; positions left and down with the pen up (invisibly).
; CONTROL-UNDERLINE (US) turns off plot mode, as does CR (for all but 4025).
; CONTROL-X switches from TEKTRONIX sub mode to NORMAL alpha mode but is
; ignored if we are emulating a full Tek terminal rather than a sub mode
; of DEC or Heath.
; FF erases screen.
; ESC letter, where letter is accent grave (`) a..e, sets the line drawing
; pattern until reset to solid lines (same as escape accent) by command or
; a terminal reset.
;
; ENQ = Control E
; ESC = Control [ (left square bracket)
; FF = Control L
; FS = Control \ (backslash)
; GS = Control ] (right square bracket)
; RS = Control ^ (caret)
; US = Control _ (underscore)
;
; The plot commands are characters which specify the absolute position to move
; the beam. All moves except the one immediately after the GS character
; (Control-]) are with a visible trace.
;
; For 4010-like devices - The positions are from 0 to 1023 for both X and Y,
; although only 0 to 780 are visible for Y due to screen geometry. The screen
; is 10.23 by 7.80 inches, and coordinates are sent as 1 to 4 characters.
;
; For 4014-like devices - The positions are from 0 to 4096, but each movement
; is a multiple of 4 positions unless the high-resolution LSBXY are sent. This
; makes it compatible with the 4010 in that a full sized plot fills the screen.
;
; HIX,HIY = High-order 5 bits of position
; LOX,LOY = Middle-order 5 bits of position
; LSBXY = Low-order 2 bits of X + low-order 2 bits of Y (4014 mode)
;
; Hi Y Lo Y Hi X LSBXY Characters sent (Lo-X always sent)
; ---- ---- ---- ----- ----------------------------------
; Same Same Same Same Lo-X
; Same Same Same Diff LSB, Lo-Y, Lo-X 4014
; Same Same Diff Same Lo-Y, Hi-X, Lo-X
; Same Same Diff Diff LSB, Lo-Y, Hi-X, Lo-X 4014
; Same Diff Same Same Lo-Y, Lo-X
; Same Diff Same Diff LSB, Lo-Y, Lo-X 4014
; Same Diff Diff Same Lo-Y, Hi-X, Lo-X
; Same Diff Diff Diff LSB, Lo-Y, Hi-X, Lo-X 4014
; Diff Same Same Same Hi-Y, Lo-X
; Diff Same Same Diff Hi-Y, LSB, Lo-Y, Lo-X 4014
; Diff Same Diff Same Hi-Y, Lo-Y, Hi-X, Lo-X
; Diff Same Diff Diff Hi-Y, LSB, Lo-Y, Hi-X, Lo-X 4014
; Diff Diff Same Same Hi-Y, Lo-Y, Lo-X
; Diff Diff Same Diff Hi-Y, LSB, Lo-Y, Lo-X 4014
; Diff Diff Diff Same Hi-y, Lo-Y, Hi-X, Lo-X
; Diff Diff Diff Diff Hi-y, LSB, Lo-Y, Hi-X, Lo-X 4014
; Offset for byte: 20h 60h 60h 20h 40h
;
; Note that LO-Y must be sent if HI-X has changed so that the TEKTRONIX knows
; the HI-X byte (in the range of 20h-3fh) is HI-X and not HI-Y. LO-Y must
; also be sent if LSBXY has changed, so that the 4010 will ignore LSBXY and
; accept LO-Y. The LSBXY byte is 60h + MARGIN*10h + LSBY*4 + LSBX. (MARGIN=0)
;
;
;
; External variable tekflg and calls to tekini, tekemu, tekesc, tekcls:
; Byte TEKFLG is non-zero when the Tek emulator is active; it is set by the
; startup code in tekini and is maintained in this file. Internal variable
; inited remembers if we have a graphics screen saved, etc.
; TEKINI must be called when entering the emulator to establish the graphics
; screen mode and to calculate the screen dimensions.
; TEKRINT reinitialize complete emulator.
; TEKESC is called from say mszibm.asm to invoke Tek emulation when the
; external procedures have detected an Escape Control-L sequence. An implicit
; initialization is done if necessary.
; TEKEMU is the normal entry point to pass a received character to the emulator.
; It too will do an implicit initialization, if required.
; TEKCLS clears the graphics screen, but only if the emulator is active.
; The emulator remains active during Connect mode Help, Status, and other
; interrupts which do not change the terminal type.
public tekemu,tekini,tekrint,tekend,tekgraf ; Terminal emulation
public tekflg, tekdmp, tekinq, tekpal, tekrpal ; used by mszibm file
public chcontrol, tekcursor, tekgcptr ; used by msyibm file
ENQ equ 05h ; ^E ENQ for TEK enquiries
CAN equ 18h ; ^X to return to ANSI mode
ESCZ equ 1Ah ; SUB, ESC-^Z triggers crosshairs
VT equ 0Bh ; ^K go up one line
FS equ 1Ch ; ^\ for point plot mode
GS equ 1Dh ; ^] draw line (1st move is invisible)
RS equ 1Eh ; ^^ for incremental line plot mode
US equ 1Fh ; ^_ (underscore) returns to text mode
accent equ 60h ; accent grave
txtmode equ 4 ; text mode for TEKTRONIX status
maxtekx equ 1024 ; horizontal and
maxteky equ 780 ; vertical resolution of TEK 4010
screen equ 10h ; IBM Bios screen call
uparr equ 72 ; DOS scan codes for arrow keys
dnarr equ 80
lftarr equ 75
rgtarr equ 77
homscn equ 71 ; DOS home screen scan code
shuparr equ '8' ; ascii codes for shifted arrows
shdnarr equ '2'
shlftarr equ '4'
shrgtarr equ '6'
mouse equ 33h ; Microsoft mouse interrupt
msread equ 3 ; mouse, read status and position
mswrite equ 4 ; mouse, set position
mshoriz equ 7 ; mouse, set min/max horizontal motion
msvert equ 8 ; mouse, set min/max vertical motion
msgetbf equ 21 ; mouse, get state buffer size
msgetst equ 22 ; mouse, get mouse state to buffer
mssetst equ 23 ; mouse, set mouse state from buffer
msreset equ 33 ; mouse, software reset
; Graph_mode for different systems:
cga equ 6 ; highest resolution mode for CGA
mono equ 7 ; real monochrome display adapter
colorega equ 14 ; Low-res mode, color EGA
monoega equ 15 ; mono ega needs mode 15
ega equ 16 ; Hi-res mode - EGA
olivetti equ 72 ; Olivetti's Hi-res - 50 lines text
toshiba equ 74h ; Toshiba T3100, like Olivetti
vaxmate equ 0D0h ; DEC VAXmate II, like Olivetti
wyse700 equ 0D3h ; Wyse-700 1280 * 400
hercules equ 255 ; pseudo mode for Hercules graphics
; Note: IBM VGA modes 17 & 18, 640 by 480, can be used by setting "ega" above
; to 17 or 18 and modifying ybot to be 479 and ymult to be 48 at label tekin5.
; The code will scale everything appropriately for the new screen size, but
; there will be insufficient memory to retain the entire graphics image.
; Manual override SET TERMINAL GRAPHICS VGA accomplishes these two steps.
;
; Note: WYSE-700 mode 1024 * 780 and 1280 * 800 can be set only by
; manual override SET TERMINAL GRAPHICS WYSET or WYSEA, respectively.
; No automatic sensing for Wyse.
segega equ 0a000h ; segments of display memory, EGA,VGA
segcga equ 0b800h ; CGA, AT&T/Olivetti and relatives
seghga equ 0b000h ; HGA
segmono equ 0b000h ; Monochrome
segwyse equ 0a000h ; wyse-700, both banks start from here
; Wyse equates:
wystoff equ 03ddh ; set bank start offset
wystseg equ 03deh ; set bank start base
wymode equ 03dfh ; register to select mode & bank
wybeven equ 0c8h ; mask for R/W even bank
wybodd equ 0cbh ; mask for R/W odd bank
; Hercules equates:
index equ 03b4h ; 6845 index register
cntrl equ 03b8h ; Display mode control port
hstatus equ 03bah ; status port
scrn_on equ 8 ; bit to turn screen on
grph equ 2 ; graphics mode
text equ 20h ; text mode
config equ 03bfh ; configuration port
genable equ 1+2 ; enable graphics (1) on two pages (2)
rgbbold equ 80 ; nor/bold threshold for RGB intensity
hiy equ 1 ; codes for Tek graphics components
loy equ 2
hix equ 4
lox equ 3
; maxparam and maxinter must agree with the prime equ's in file mszibm.asm
maxparam equ 10 ; number of ESC and DCS Parameters
maxinter equ 10 ; number of ESC and DCS Intermediates
; Pixel basic operation codes
pixor equ 1 ; write as foreground OR current dot
pixbak equ 2 ; write as absolute background color
pixxor equ 4 ; write as foreground XOR current dot
pixfor equ 8 ; write absolute foreground color
data segment
extrn flags:byte, portval:word, rxtable:byte, vtemu:byte
extrn tv_mode:byte, yflags:byte, low_rgt:byte
extrn param:word, nparam:word, inter:byte, ninter:word, lparam:byte
extrn parstate:word, pardone:word, parfail:word
extrn dnparam:word, dparam:word, dlparam:byte, dninter:word
extrn dinter:byte, dcsstrf:byte, emubufc:word, emubuf:byte
extrn emubufl:word, ttyact:byte, vtclear:byte
; required for Hercules screen handling
gtable db 35h,2dh,2eh,7 ; bytes for 6845 controller
db 5bh,2,57h,57h ; - graphics mode
db 2,3,0,0
ttable db 61h,50h,52h,0fh ; bytes for 6845 controller
db 19h,6,19h,19h ; - text mode
db 2,0dh,0bh,0ch
attlogo db 'OLIVETTI' ; Olivetti M24/28, AT&T 6300 rom id
attllen equ $-attlogo ; length
toshlogo db ' TT33110000 TTOOSSHHIIBBAA' ; Toshiba T3100 logo
toshlen equ $-toshlogo ; length
declogo db 'Copyright Digital Equipment Corp' ; DEC VAXmate
declen equ $-declogo
dumpname db 'TEKPLT.TIF',0 ; dump name
dumplen equ $-dumpname
tempname db 84 dup (0) ; temp work area
dhandle dw -1 ; dump file handle
ttstate dw tektxt ; state machine control pointer
prestate dw 0 ; previous state, across interruptions
visible db 0 ; 0 to move, 1 to draw a line
tek_hiy dw 0 ; Y coordinate in Tektronix mode
tek_loy db 0
tek_hix dw 0 ; X coordinate in Tektronix mode
tek_lox db 0
tek_lsb db 0 ; Low-order 2 bits of X + low Y
; (4014 mode)
status db 0
lastc db 0 ; last x/y coord fragment seen
bnkchan db 0 ; a flag so we can select which bank
; to write in Wyse 1280*800 mode
colpal db 0,9,0ch,0ah ; VT340 color palette table, IRGB
db 0dh,0bh,0eh,7, 8,1,4,2, 5,3,6,0fh ; 16 bytes, active table
db 256-($-colpal) dup (0) ; to make 256 entries overall
coldef db 0,9,0ch,0ah, 0dh,0bh,0eh,7, 8,1,4,2, 5,3,6,0fh ; color def
mondef db 0,7 dup (0fh), 8 dup (7) ; monochrome default "colors"
havepal db 0 ; 1 if have selected palette
masktab db 80h,40h,20h,10h,8,4,2,1 ; quicker than calculations!
; dashed line patterns
linetab dw 0ffffh ; ESC accent 11111111 11111111
dw 0aaaah ; ESC a 10101010 10101010
dw 0f0f0h ; ESC b 11110000 11110000
dw 0fafah ; ESC c 11111010 11111010
dw 0ffcch ; ESC d 11111111 11001100
dw 0fc92h ; ESC e 11111100 10010010
dw 0ffffh ; ESC x user defined
dw 0ffffh ; ESC y user defined
dw 0ffffh ; ESC z user defined
linepat dw 0ffffh ; active line pattern, from above
tekid db escape,'[?63;1;2;4;8;9;15c',0; VT320, level 3, etc
;End of init data
even
xmult dw 1 ; scaling factor for x is
xdiv dw 1 ; xmult/xdiv
ymult dw 1 ; scaling factor for y is
ydiv dw 1 ; ymult/ydiv
xmax dw 1 ;
ybot dw 1 ;
x_coord dw 0 ; Tek text char X coordinate
y_coord dw 0 ; Tek text char Y coordinate
xcursor dw 0 ; PC x_coord of text cursor symbol
ycursor dw 0 ; PC y_coord of text cursor symbol
xcross dw 0 ; crosshair coordinates
ycross dw 0
xcenter dw 0 ; center of screen
ycenter dw 0 ; center of screen
tekcursor db 1 ; show text cursor (non-zero)
cursorst db 0 ; cursor state (non-zero is displayed)
oldx dw 0 ; Tek coordinates of last point
oldy dw 767 ; initially top left
scalex dw 0 ; PC coord for scaled x value
scaley dw 0 ; for scaled y value
rectx1 dw 0 ; Rectangle PC x lower left corner
recty1 dw 0 ; Rectangle PC y lower left corner
rectx2 dw 0 ; Rectangle PC x width
recty2 dw 0 ; Rectangle PC y height
numlines dw 0 ; number of lines to fill
; area fill material
fill db 0 ; current fill byte pattern
fillptr dw filpat1 ; pointer to current fill pattern
fillist dw filpat1,filpat2,filpat3,filpat4,filpat5,filpat6,filpat7
dw filpat8,filpat9,filpat10,filpat11,filpat12,filpat13
dw filpat14
numfil equ ($-fillist)/2 ; number of fill patterns
; fill patterns, 8 bits wide, first byte is at top of PC screen
; 8 bytes per pattern for 8 scan line repetition
filpat1 db 8 dup (0ffh) ; solid fill
filpat2 db 4 dup (0aah, 55h) ; grey (alternating dots)
filpat3 db 80h,01h,02h,04h, 08h,10h,20h,40h ; right to left slant up
filpat4 db 80h,40h,20h,10h, 08h,04h,02h,01h ; left to right slant up
filpat5 db 2 dup (0,0,0aah,0) ; horizontal lines
filpat6 db 8 dup (44h) ; vertical lines
filpat7 db 80h,41h,22h,14h, 08h,14h,22h,41h ; slanted crosshatch
filpat8 db 2 dup (0aah,80h,80h,80h) ; vertical crosshatch
filpat9 db 4 dup (0f0h), 4 dup (0fh) ; checkerboard
filpat10 db 4 dup (44h, 11h) ; dots
filpat11 db 2 dup (10h,28h,44h,82h) ; horizontal herringbone
filpat12 db 80h,40h,20h,10h,08h,10h,20h,40h ; vertical herringbone
filpat13 db 8 dup (0ffh) ; first user definable fill
filpat14 db 8 dup (0ffh) ; second user definable fill
; end of area fill material
curmode db 0 ; screen mode before graphics
tekgraf db 0 ; Tek graphics board selection (def=auto)
; local variables for LINE plotting routine
graph_mode db 0 ; graphics video mode, default is none
cursor dw 0 ; saved text cursor
inited db 0 ; non-zero if inited (retains page)
tekflg db 0 ; Tek mode active flag
; 1=Tek reads serial port
; 2=VT300 emulator reads serial port
tekident db 0 ; Tek ident request flag
flow dw 0 ; flow control word
gpage db 0 ; display adapter graphics page
gfcol db 15 ; graphics foreground colour
gbcol db 0 ; graphics background color
tfcol db 0 ; temp foreground color
tbcol db 0 ; temp background color
colortb db 0,4,2,6,1,5,3,7 ; color reversed-bit setting bytes
ccode db pixfor ; temp for holding plot color code
bypass db 0 ; GIN mode bypass condition (0=off)
esctype db 0 ; first char after ESCAPE char
bscontrol db 0 ; non-zero for destructive BS
spcontrol db 0 ; non-zero for destructive SPACE
chcontrol db 0 ; char-writing, 1=opaque,0=transparent
even
mousebuf dw 0 ; segment of mouse save buffer
putc dw mputc ; ptr to plot a character routine
psetup dw psetupm ; ptr to plot setup routine
pincy dw pincym ; ptr to inc y routine
plotptr dw pltmon ; ptr to dot plot routine
gfplot dw bpltmon ; ptr to area-fill plot routine
segscn dw 0b800h ; actual screen segment to use
doneptr dw offset xpardone,seg xpardone ; far pointer for tpardone use
dumpptr dw offset dump,seg dump ; far pointer for dump use
initptr dw offset tekini,seg tekini
rptptr dw offset tekrpt,seg tekrpt
endptr dw offset tekend,seg tekend
tekpptr dw offset tekxco4,seg tekxco4
linelen dw 0 ; offset increment between scan lines
ten dw 10 ; word 10 for multiplying
temp dw 0
; 8*8 font for Hercules and such, CGA, and EGA
; - allows 43 lines, and 80 (90 for Hercules) chars per line.
; all printing (?) characters from <space> to <del> - two characters per line
; 8 bits per scan line, top line given first, 8 scan lines.
font db 0,0,0,0,0,0,0,0, 18h,18h,18h,18h,18h,0,18h,0
db 6ch,6ch,6ch,0,0,0,0,0, 36h,36h,7fh,36h,7fh,36h,36h,0
db 0ch,3fh,68h,3eh,0bh,7eh,18h,0, 60h,66h,0ch,18h,30h,66h,06h,0
db 38h,6ch,6ch,38h,6dh,66h,3bh,0, 0ch,18h,30h,0,0,0,0,0
db 0ch,18h,30h,30h,30h,18h,0ch,0, 30h,18h,0ch,0ch,0ch,18h,30h,0
db 0,18h,7eh,3ch,7eh,18h,0,0, 0,18h,18h,7eh,18h,18h,0,0
db 0,0,0,0,0,18h,18h,30h, 0,0,0,7eh,0,0,0,0
db 0,0,0,0,0,18h,18h,0, 0,06h,0ch,18h,30h,60h,0,0
db 3ch,66h,6eh,7eh,76h,66h,3ch,0, 18h,38h,18h,18h,18h,18h,7eh,0
db 3ch,66h,06h,0ch,18h,30h,7eh,0, 3ch,66h,06h,1ch,06h,66h,3ch,0
db 0ch,1ch,3ch,6ch,7eh,0ch,0ch,0, 7eh,60h,7ch,06h,06h,66h,3ch,0
db 1ch,30h,60h,7ch,66h,66h,3ch,0, 7eh,06h,0ch,18h,30h,30h,30h,0
db 3ch,66h,66h,3ch,66h,66h,3ch,0, 3ch,66h,66h,3eh,06h,0ch,38h,0
db 0,0,18h,18h,0,18h,18h,0, 0,0,18h,18h,0,18h,18h,30h
db 0ch,18h,30h,60h,30h,18h,0ch, 0,0,0,7eh,0,7eh,0,0,0
db 30h,18h,0ch,06h,0ch,18h,30h, 0,3ch,66h,0ch,18h,18h,0,18h,0
db 3ch,66h,6eh,6ah,6eh,60h,3ch, 0,3ch,66h,66h,7eh,66h,66h,66h,0
db 7ch,66h,66h,7ch,66h,66h,7ch, 0,3ch,66h,60h,60h,60h,66h,3ch,0
db 78h,6ch,66h,66h,66h,6ch,78h, 0,7eh,60h,60h,7ch,60h,60h,7eh,0
db 7eh,60h,60h,7ch,60h,60h,60h, 0,3ch,66h,60h,6eh,66h,66h,3ch,0
db 66h,66h,66h,7eh,66h,66h,66h, 0,7eh,18h,18h,18h,18h,18h,7eh,0
db 3eh,0ch,0ch,0ch,0ch,6ch,38h, 0,66h,6ch,78h,70h,78h,6ch,66h,0
db 60h,60h,60h,60h,60h,60h,7eh, 0,63h,77h,7fh,6bh,6bh,63h,63h,0
db 66h,66h,76h,7eh,6eh,66h,66h, 0,3ch,66h,66h,66h,66h,66h,3ch,0
db 7ch,66h,66h,7ch,60h,60h,60h, 0,3ch,66h,66h,66h,6ah,6ch,36h,0
db 7ch,66h,66h,7ch,6ch,66h,66h, 0,3ch,66h,60h,3ch,06h,66h,3ch,0
db 7eh,18h,18h,18h,18h,18h,18h, 0,66h,66h,66h,66h,66h,66h,3ch,0
db 66h,66h,66h,66h,66h,3ch,18h, 0,63h,63h,6bh,6bh,7fh,77h,63h,0
db 66h,66h,3ch,18h,3ch,66h,66h, 0,66h,66h,66h,3ch,18h,18h,18h,0
db 7eh,06h,0ch,18h,30h,60h,7eh, 0,7ch,60h,60h,60h,60h,60h,7ch,0
db 0,60h,30h,18h,0ch,06h,0,0, 3eh,06h,06h,06h,06h,06h,3eh,0
db 18h,3ch,66h,42h,0,0,0,0, 0,0,0,0,0,0,0,0ffh
db 30h,18h,0ch,0,0,0,0,0, 0,0,3ch,06h,3eh,66h,3eh,0
db 60h,60h,7ch,66h,66h,66h,7ch,0, 0,0,3ch,66h,60h,66h,3ch,0
db 06h,06h,3eh,66h,66h,66h,3eh,0, 0,0,3ch,66h,7eh,60h,3ch,0
db 0eh,18h,18h,3ch,18h,18h,18h,0, 0,0,3eh,66h,66h,3eh,06h,3ch
db 60h,60h,7ch,66h,66h,66h,66h,0, 18h,0,38h,18h,18h,18h,3ch,0
db 18h,0,38h,18h,18h,18h,18h,70h, 60h,60h,66h,6ch,78h,6ch,66h,0
db 38h,18h,18h,18h,18h,18h,3ch,0, 0,0,76h,7fh,6bh,6bh,63h,0
db 0,0,7ch,66h,66h,66h,66h,0, 0,0,3ch,66h,66h,66h,3ch,0
db 0,0,7ch,66h,66h,7ch,60h,60h,0, 0,3eh,66h,66h,3eh,06h,07h
db 0,0,6ch,76h,60h,60h,60h,0, 0,0,3eh,60h,3ch,06h,7ch,0
db 30h,30h,7ch,30h,30h,30h,1ch,0, 0,0,66h,66h,66h,66h,3eh,0
db 0,0,66h,66h,66h,3ch,18h,0, 0,0,63h,6bh,6bh,7fh,36h,0
db 0,0,66h,3ch,18h,3ch,66h,0, 0,0,66h,66h,66h,3eh,06h,3ch
db 0,0,7eh,0ch,18h,30h,7eh,0, 0ch,18h,18h,70h,18h,18h,0ch,0
db 18h,18h,18h,0,18h,18h,18h,0, 30h,18h,18h,0eh,18h,18h,30h,0
db 31h,6bh,46h,0,0,0,0,0, 0ffh,6 dup (81h),0ffh
; note, the last 8 bytes comprise the text cursor symbol pattern
; TIFF version 5.0 data fields
; Reference: Aldus/Microsoft Technical Memorandum dated 8/8/88
; TIFF data item size indicators
uchar equ 1 ; unsigned byte
ascii equ 2 ; asciiz string byte
integer equ 3 ; 16 bit unsigned integer
long equ 4 ; 32 bit unsigned integer
rational equ 5 ; 32 bit numerator, 32 bit denominator
entry struc ; 12 byte image file directory entries
dw ? ; tag
dw integer ; type, of data item
entcnt dd 1 ; length, count of data items
entval dw 0 ; long value or long offset to value
dw 0
entry ends
even ; TIFF 5.0, 8 byte header
header dw 4949h ; 'll', low byte stored first
dw 42 ; TIFF identification, 42 decimal
dw nentry-header,0 ; long offset to image file directory
; Image File Directory
nentry dw entrycnt ; number of entries to follow
; 12-byte directory entries
newsub entry <0feh,long> ; new subfield type
iwidth entry <100h,integer> ; image width, integer for WP 5
ilength entry <101h,integer> ; image length, integer for WP 5
bps entry <102h,,,4> ; bits per sample, 4=iRGB, 1=B/W
comp entry <103h,,,1> ; compression, none
photo entry <106h,,,3> ; photometric interpret, palette
strip entry <111h,long,25,stripoff-header> ; offset to long strip offsets
spp entry <115h,,,1> ; samples/pixel, 1
rps entry <116h,long,1,25> ; long rows per strip
sbc entry <117h,integer,25,stripbc-header> ; offset to strip byte counts
xres entry <11ah,rational,1,xresval-header> ; x axis resolution
yres entry <11bh,rational,1,yresval-header> ; y axis resolution
resunit entry <128h,integer,1,1> ; resolution unit, no absolute units
soft entry <131h,ascii,proglen,prog-header> ; software ident
stamp entry <132h,ascii,dtlen,dandt-header> ; date and time stamp
cmap entry <140h,integer,3*16,colmap-header> ; palette color map
entrycnt equ ($-nentry-2+11)/12 ; compute number of entries for nentry
dd 0 ; long offset of next directory (none)
; supporting data pointed at above
prog db 'MS Kermit 300',0 ; originating program, asciiz
proglen equ $-prog
dandt db '1989:12:25 00:00:01',0 ; date and time format
dtlen equ $-dandt
xresval dw 0,0,1,0 ; two double words (top / bottom)
yresval dw 0,0,1,0 ; two double words (top / bottom)
stripoff dd 25 dup (0) ; long file offset for each strip
stripbc dw 25 dup (0) ; integer byte count for each strip
; color map for red, green, blue; index by IRGB bits from ega sample
colmap dw 4 dup (0), 4 dup (007ffh), 4 dup (0), 4 dup (0ffffh) ; red
dw 2 dup (0,0,007ffh,007ffh), 2 dup (0,0,0ffffh,0ffffh) ; green
dw 2 dup (0,007ffh,0,007ffh), 2 dup (0,0ffffh,0,0ffffh) ; blue
tifflen equ $-header ; length of header + directory + info
pixdata equ $ ; pixel data start here on disk
; end of TIFF information
esctab db 34 ; table of ESC <char> dispatches
dw escjmp ; address of table for action routines
db ENQ,FF,CAN,CTLZ,'/' ; ^E,^L,^X,^Z,/
db '2','@ABCD','EFGHI','JKLM'
db 3fh,'PZ[\' ; '?PZ[\'
db 60h,'abcde','xyz' ; accent, a..e,x,y,z
; Dispatch for esctab table
even
escjmp dw tekenq, tekcls,tekcan, tekgin,tekeseq ; ^E,^L,^X,^Z,/
dw tektwo,14 dup (tekfill) ; '2@ABCDEFGHIJKLM'
dw tekqury,tekeseq,sendid,tekeseq,tekgotst ; '?PZ[\'
dw 9 dup (teklpat) ; accent, a..e,x,y,z
; Final char table for ANSI escape sequences
anstab db 21 ; number of entries
dw ansjmp ; address of action routines
db '@ABCD','EFGHJ','KXade','fhlmn','u'
; Dispatch for anstab table
even
ansjmp dw ansich, atcuu, atcud, atcuf, atcub ; '@ABCD'
dw atcnl, atcpl, atcha, atcup, ated ; 'EFGHJ'
dw atel, atech, atcuf, atcva, atcud ; 'KXade'
dw atcup, escexit, escexit, tekcol, tekrid ; 'fhlmn'
dw tekprpt ; 'u'
data ends
code segment ; main body code segment
extrn outchr:near, beep:near, scrseg:near, cmblnk:near
extrn savescr:near, restscr:near, cptchr:near, clrbuf:near
extrn iseof:near, atparse:near, unique:near
extrn chgdsp:near, pcwait:near, vtrmac:near, vtsmac:near
assume cs:code, ds:data, es:nothing
; These far routines are called by the Tek emulator; they are here to provide
; a bridge to the main code segment near procedures.
; Procedures for calling to the main body of MS Kermit. Most are FAR and
; must be in in code segment named code, not in code2.
outmodem proc far ; send Tek char out serial port
push ax
mov ah,al
call outchr ; outchr reads from ah
pop ax
ret
outmodem ENDP
tekbeep proc far ; sound a beep from Tek mode
call beep
ret
tekbeep endp
tcmblnk proc far ; blank the screen from Tek mode
call cmblnk
ret
tcmblnk endp
tsavescr proc far ; save text screen while in Tek mode
call savescr
ret
tsavescr endp
trestscr proc far ;restore text screen while in Tek mode
cmp low_rgt,80 ; were we in 80 column mode?
jbe trestsc1 ; be = yes
mov al,1 ; set to 132 columns
call chgdsp ; msyibm routine to change screen
trestsc1:
call restscr
ret
trestscr endp
tscrseg proc far ; get video segment while in Tek mode
call scrseg
ret
tscrseg endp
tcptchr proc far ; call session logger while in Tek
call cptchr ; mode
ret
tcptchr endp
tiseof proc far ; call iseof while in Tek mode
call iseof
ret
tiseof endp
tparstart proc far ; start escape sequence parser
mov parstate,0 ; set to initialize automatically
mov pardone,offset tpardone ; jmp to this when completed
mov parfail,0 ; no failure case jump
ret
tparstart endp
tparser proc far
call atparse ; reach to real parser
ret
tparser endp
tpardone proc near ; called by real parser
call dword ptr doneptr ; far call xpardone, old MASM way
ret
tpardone endp
tunique proc far ; reach to real unique name procedure
call unique ; while in Tek mode
ret
tunique endp
tekwait proc far ; call pcwait while in Tek mode
call pcwait
ret
tekwait endp
; Return screen info for Tek screen report: ax=screen height, bx=width,
; cx=number of colors (0=none for pure text, 1=b/w, 16=ega)
tekinq proc near
mov tekident,1 ; say this is an ident request
call dword ptr initptr ; do init steps to get screen sizes
mov ax,ybot ; lowest screen line
inc ax ; screen height, in lines
mov bx,xmax
add bx,8 ; screen width, in dots
cmp graph_mode,mono ; pure text mono (no graphics at all)?
jne tekinq1 ; ne = no
mov ax,24 ; bottom screen line
mov bx,80 ; screen width
xor cx,cx ; pure mono, say 0 colors
jmp short tekinq2
tekinq1:mov cx,1 ; say b/w screen
cmp plotptr,offset pltcga ; using CGA style graphics?
je tekinq2 ; e = yes
cmp graph_mode,monoega ; monochrome monitor on ega?
je tekinq2 ; e = yes
mov cx,16 ; say 16 colors
tekinq2:mov tekident,0
ret
tekinq endp
; Return in BX the offset of the master color palette table. Used by SET TERM
; GRAPHICS COLOR <color value> to obtain foreground and background colors
; in palette slots 7 and 0, resp.
tekgcptr proc near
mov tekident,1 ; say this is an ident request
call dword ptr initptr ; do init steps to get screen sizes
mov bx,offset mondef ; default monochrome colors
cmp plotptr,offset pltcga ; using CGA style graphics?
je tekgcpt1 ; e = yes
cmp graph_mode,mono ; pure mono text system?
je tekgcpt1 ; e = yes
cmp graph_mode,monoega ; ega, but monochrome?
je tekgcpt1 ; e = no
mov bx,offset coldef ; return offset of color palette
tekgcpt1:mov havepal,0 ; say don't have a palette setup
mov tekident,0
mov inited,0
ret
tekgcptr endp
; These routines can be called by either the main body or from within Tek
; mode.
tekdmp proc near ; Tek screen dump routine
call dword ptr dumpptr ; callable from main body
clc
ret
tekdmp endp
tekmac proc far ; invoke vtrmac or vtsmac
or ax,ax ; which macro?
jz tekmacr ; z = the R flavor
call vtsmac ; do TerminalS, in msyibm
ret
tekmacr:call vtrmac ; do TerminalR, in msyibm
ret ; only if they fail
tekmac endp
tekpal proc near ; do palette report tekrpt
call dword ptr rptptr ; callable from main body
ret
tekpal endp
tekrpal proc near ; restore color palette
call dword ptr tekpptr ; callable from main body
ret
tekrpal endp
code ends ; main body code segment
; Code segment code2 is allocated to Tektronix emulation
code2 segment ; supplementary code segment
assume cs:code2, ds:data, es:nothing
cs2pb db 256 dup (0) ; code2 segment patch buffer
tekxco4 proc FAR ; call local tekgco4, return far
call tekgco4
ret
tekxco4 endp
; Initialise TEK mode by setting high resolution screen, etc
tekini proc far
push ax ; do presence tests
push bx
push cx
push dx
push si
push di
push es
cmp tekident,0 ; just identifying?
jne tekin0 ; ne = yes
mov bx,portval ; get port flow control chars:
mov bx,[bx].flowc ; bh=xon, bl=xoff or both are nulls
mov flow,bx ; save here
mov ax,bx ; get flow control word
or al,al ; able to do xoff?
jz tekin0 ; z = no
call outmodem ; tell host xoff while we change modes
tekin0: cmp inited,0 ; inited yet?
jne tekin0a ; ne = yes, use existing coloring
mov ax,linetab ; get default line pattern
mov linepat,ax ; init active line pattern
mov fillptr,offset filpat1 ; init active fill pointer
cmp havepal,0 ; have a color palette yet?
jne tekin0a ; ne = yes
mov bx,vtemu.att_ptr ; emulator screen color ptr
mov al,[bx]
mov gfcol,al ; save foreground color
and gfcol,0fh ; save just foreground bits
and al,70h ; select background color, no bold
mov cl,4
shr al,cl ; get background colors
mov gbcol,al ; set graphics background color
tekin0a:mov ah,15 ; get current screen mode
int screen
and al,not 80h ; strip "preserve regen" bit 80h
cmp al,mono ; mono text mode (7)?
je tekin1 ; e = yes
cmp tekident,0 ; doing an ident request?
jne tekin2 ; ne = yes, don't mess with screen
test tekflg,1 ; are we active as Tek device now?
jz tekin1 ; z = no
jmp tekin13 ; yes, don't redo graphics setup
tekin1: mov curmode,al ; save mode here
mov ah,3 ; get cursor position
xor bh,bh ; page 0
int screen
mov cursor,dx ; save position
call tsavescr ; save text screen
; Presence tests.
tekin2: mov graph_mode,cga ; Color. Assume CGA
mov segscn,segcga ; assume cga screen segment
mov gpage,0 ; graphics page 0 but no page 1
mov putc,offset gputc ; CGA character display routine
mov gfplot,offset bpltcga ; CGA area fill routine
mov psetup,offset psetupc ; CGA plot setup routine
mov plotptr,offset pltcga ; CGA dot plot routine
mov pincy,offset pincyc ; CGA inc y routine
mov xmult,5 ; CGA. Scale TEK to PC by 640/1024
mov xdiv,8 ; so that 0-1023 converts to 0-639
mov xmax,640-8 ; x-coord of rightmost character
mov ymult,10 ; vertical scale for IBM is 200/780
mov ydiv,39 ;
mov ybot,199 ; Bottom of screen is Y=199
mov al,tekgraf ; user video board specification
or al,al ; auto-sensing?
jnz tekin2d ; nz = no
jmp tekin2c ; yes (default)
tekin2d:cmp al,1 ; user wants CGA?
jne tekin2a ; ne = no
jmp tekin13 ; do CGA
tekin2a:cmp al,4 ; user wants Hercules?
jne tekin2b ; ne = no
jmp tekin8 ; do Hercules
tekin2b:cmp al,5 ; user wants AT&T style?
jne tekinwy ; ne = no
jmp tekin7 ; do AT&T kind
; Wyse-700
tekinwy:cmp al,8 ; user wants Wyse-700 1024*780 ?
jne tekinw0 ; ne = no
call chkwyse ; presence test
jc tekinwf ; c = failed
mov xmax,1024-8 ; x-coord of rightmost character
mov ybot,779 ; Bottom of screen is Y=780
mov xmult,1 ; Wyse. Scale TEK to PC by 1024/1024
mov xdiv,1 ; so that 0-1023 converts to 0-1023
mov ymult,1 ; vertical scale is 780/780
mov ydiv,1 ;
jmp short tekinw2 ;
tekinw0:cmp al,7 ; user wants Wyse-700 1280*780 ?
jne tekinw1 ; ne = no
call chkwyse ; presence test
jc tekinwf ; c = failed
mov xmax,1280-8 ; x-coord of rightmost character
mov ybot,779 ; Bottom of screen is Y=800
mov xmult,10 ; Wyse. Scale TEK to PC by 1280/1024
mov xdiv,8 ; so that 0-1023 converts to 0-1279
mov ymult,1 ; vertical scale is 780/780
mov ydiv,1 ;
jmp short tekinw2 ;
tekinwf:jmp tekin2c ; failure jump point
tekinw1:cmp al,6 ; user wants Wyse-700 1280*800 ?
jne tekin2c ; no = no
call chkwyse ; presence test
jc tekinwf ; c = failed
mov xmax,1280-8 ; x-coord of rightmost character
mov ybot,799 ; Bottom of screen is Y=800
mov xmult,10 ; Wyse. Scale TEK to PC by 1280/1024
mov xdiv,8 ; so that 0-1023 converts to 0-1279
mov ymult,40 ; vertical scale for IBM is 800/780
mov ydiv,39 ; so scale those 20 pixels more
tekinw2:mov graph_mode,wyse700 ; Assume Wyse Graphics
mov segscn,segwyse ; assume wyse screen segment
mov gpage,0 ; only one graphics page 0
mov putc,offset gputc ; CGA character display routine
mov psetup,offset psetupw ; Wyse plot setup routine
mov plotptr,offset pltcga ; CGA dot plot routine
mov pincy,offset pincyw ; Wyse inc y routine
jmp tekin13 ; do Wyse
; do auto-sensing of display board
; test for EGA
tekin2c:mov ax,1200H ; EGA: Bios alternate select
mov bl,10H ; Ask for EGA info
mov bh,0ffH ; Bad info, for testing
mov cl,0fH ; Reserved switch settings
int screen ; EGA, are you there?
and cl,0fh ; four lower switches
cmp cl,0cH ; Test reserved switch settings
jb tekin3 ; b = ega present
jmp tekin7 ; else no EGA, check other adapters
tekin3: mov ax,40h ; check Bios 40:87h for ega being
mov es,ax ; the active display adapter
test byte ptr es:[87h],8 ; is ega active?
jz tekin3a ; z = yes
jmp tekin7 ; ega is inactive, check others
tekin3a:cmp bl,1 ; is there 128KB on ega board?
jb tekin4 ; b = less, so no screen saves
mov gpage,1 ; >=128 KB, use two graphics pages
tekin4: mov graph_mode,ega ; assume high resolution color
cmp cl,3 ; high resolution color?
je tekin5 ; e = yes
cmp cl,9 ; high resolution color?
je tekin5 ; e = yes
mov graph_mode,monoega ; assume mono monitor on ega board
test bh,1 ; ega mono mode in effect?
jnz tekin5 ; nz = yes
mov graph_mode,colorega ; say ordinary cga on ega board, 64KB
mov gpage,1 ; is enough memory with 200 scan lines
jmp short tekin5a ; use current cga parameters
tekin5: mov ybot,349 ; text screen bottom is 349 on EGA
mov ymult,35 ;
mov ydiv,78 ; scale y by 350/780
tekin5a:mov segscn,segega ; use ega screen segment
mov psetup,offset psetupe ; plot setup routine
mov plotptr,offset pltega ; ega dot plot routine
mov gfplot,offset bpltega ; ega area fill routine
mov pincy,offset pincye ; inc y routine
mov putc,offset gputc ; character display routine
jmp tekin13 ; end of EGA part, do VGA tests below
tekin7: mov ax,0fc00h ; Olivetti/AT&T 6300, check rom id
mov es,ax
xor di,di ; start here
mov graph_mode,olivetti ; Olivetti
mov cx,attllen ; length of logo
mov si,offset ATTLOGO ; master string
repe cmpsb ; do a match
je tekin7c ; e = a match
mov di,0050h ; look here too
mov si,offset ATTLOGO
mov cx,attllen
repe cmpsb
je tekin7c ; e = a match
mov di,2014h ; and look here
mov si,offset ATTLOGO
mov cx,attllen
repe cmpsb ; do a match
je tekin7c ; e = a match, else try other types
tekin7a:mov graph_mode,toshiba
mov ax,0f000h ; Check for Toshiba T3100, rom scan
mov es,ax
mov di,0014h ; start here
mov si,offset TOSHLOGO ; master string
mov cx,toshlen ; length
repe cmpsb ; do a match
je tekin7c ; e = a match, else try other types
tekin7b:mov graph_mode,vaxmate ; DEC VAXmate II
mov ax,0f000h ; Check for VAXmate II rom signature
mov es,ax
mov di,0e000h ; start here
mov si,offset DECLOGO ; master string
mov cx,declen ; length
repe cmpsb ; do a match
jne tekin7d ; ne = mismatch, try other types
; Olivetti/AT&T, Toshiba, VAXmate
tekin7c:mov gpage,0 ; only page 0 with 640 by 400 mode
mov segscn,segcga ; use cga screen segment (0b800h)
mov psetup,offset psetupo ; plot setup routine
mov plotptr,offset pltcga ; cga dot plot routine
mov gfplot,offset bpltcga ; area fill plot routine
mov pincy,offset pincyh ; inc y routine (Herc style addresses)
mov putc,offset gputc ; character display routine
mov ybot,399 ; bottom of screen is y = 399
mov ymult,20 ; vertical scale = 400/780
mov ydiv,39 ; same as cga setup
jmp tekin13
tekin7d:cmp curmode,mono ; mono text mode?
je tekin8 ; e = yes
jmp tekin11 ; ne = no, try cga
; test for Hercules
tekin8: call tscrseg ; get screen segment, test Environment
cmp tv_mode,1 ; Environment active?
jne tekin8a ; ne = no, ok to test for Hercules
jmp tekin10 ; don't do Herc mode, do Mono
tekin8a:mov dx,hstatus ; Herc status port
in al,dx ; read it
mov bl,al ; save here
and bl,80h ; remember retrace bit
mov cx,0ffffh ; do many times (for fast machines)
tekin8b:mov dx,hstatus ; check status port
in al,dx
and al,80h ; select bit
jmp $+2 ; use a little time
cmp bl,al ; did it change?
loope tekin8b ; test again if not
je tekin10 ; e = no change in bit, not Herc
mov graph_mode,hercules ; say have Herc board
mov segscn,seghga ; assume hga screen segment
mov putc,offset gputc ; character display routine
mov gfplot,offset bpltcga ; area fill plot routine
mov psetup,offset psetuph ; plot setup routine to use
mov plotptr,offset pltcga ; use cga dot plot routine for Herc
mov pincy,offset pincyh ; inc y routine
mov xmult,45 ; Scale TEK to Hercules by 720/1024
mov xdiv,64 ; so that 0-1023 converts to 0-719
mov xmax,720-8 ; x-coord of rightmost character
mov ymult,87 ; vertical scale for Hercules is
mov ydiv,195 ; 348/780
mov ybot,347 ; bottom of screen is y = 347
mov ax,seghga ; segment of Herc video display
mov es,ax
mov al,es:[8000h] ; read original contents, page 1
not byte ptr es:[8000h] ; write new pattern
mov ah,es:[8000h] ; read back
not byte ptr es:[8000h] ; restore original contents
not ah ; invert this too
cmp ah,al ; same (memory present?)
jne tekin9 ; ne = not same, no memory there
mov gpage,1 ; say two pages of display memory
tekin9: call crossini ; preset crosshairs
jmp tekin13
; set to MONO
tekin10:mov graph_mode,mono ; force monochrome adapter text
mov segscn,segmono ; assume mono screen segment
call tscrseg ; Environments: get virtual screen
mov segscn,ax ; seg returned in ax and es:di
mov gpage,0
mov putc,offset mputc ; character display routine
mov psetup,offset psetupm ; plot setup routine to use
mov gfplot,offset bpltmon ; area fill plot routine
mov plotptr,offset pltmon ; use hga dot plot routine
mov pincy,offset pincym ; inc y routine
mov xmult,5 ; Scale TEK to mono by 640/1024
mov xdiv,8 ; so that 0-1023 converts to 0-639
mov xmax,640-8 ; x-coord of rightmost character
mov ymult,10 ; vertical scale for mono is 200/780
mov ydiv,39
mov ybot,200 ; bottom of screen is y = 200 for Bios
jmp tekin13 ; Uses TEXT mode, for safety
; test for CGA
tekin11:mov graph_mode,cga ; set CGA high resolution graphics
mov segscn,segcga ; CGA screen segment
jmp tekin13
; Set Graphics mode
tekin13:cmp tekident,0 ; just identifying?
je tekin13b ; e = no
jmp tekin16 ; ne = yes
tekin13b:cmp graph_mode,wyse700 ; Wyse ?
jne tekin13a ; ne = no
call wygraf ; set Wyse graphics mode, clear regen
jmp tekin16 ; restore screen
tekin13a:cmp graph_mode,hercules ; Hercules?
jne tekin14 ; ne = no
call hgraf ; set Herc graphics mode, clear regen
or tekflg,1 ; say doing Tekmode
jmp tekin16 ; restore screen
tekin14:xor ah,ah ; set screen mode
mov al,graph_mode ; to this screen mode
cmp tekgraf,3 ; user wants "VGA" modes (640x480)?
jne tekin14a ; ne = no
push ax
mov ax,1a00h ; VGA, read display config code
int screen
pop ax
cmp bl,0bh ; MCGA mono?
jne tekin14b ; ne = no
mov al,monoega
mov graph_mode,al
jmp short tekin14c
tekin14b:cmp bl,0ch ; MCGA color?
jne tekin14d ; ne = no
mov al,ega
mov graph_mode,al
tekin14c:mov ydiv,78 ; scale y by 350/780
mov segscn,segega ; use ega screen segment
mov psetup,offset psetupe ; plot setup routine
mov plotptr,offset pltcga ; ega dot plot routine
mov gfplot,offset bpltcga ; ega area fill routine
mov pincy,offset pincye ; inc y routine
mov putc,offset gputc ; character display routine
tekin14d:
cmp al,monoega ; yes, allow high resolution stuff?
jb tekin14a ; b = no
cmp al,ega ; ditto
ja tekin14a ; a = no
add al,2 ; use modes 17(b/w) and 18(10)(color)
mov ybot,479 ; text screen bottom is 479 on VGA
mov ymult,48
tekin14a:cmp tekident,0 ; just identifying screen size etc?
jne tekin16 ; ne = yes, do not invoke graphics
cmp gpage,0 ; only page 0 available?
je tekin15 ; e = yes, and watch for Bios errors
cmp inited,0 ; first time through?
je tekin15 ; e = yes, clear the page of old junk
or al,80h ; save regen buffer (save area too)
tekin15:int screen ; Bios Set Mode.
mov ax,40h ; DOS 4 GRAPHICS.COM may see high bit
mov es,ax ; and be confused. Clear it from Bios
and byte ptr es:[49h],7fh ; word area for some clones
or tekflg,1 ; say doing Tekmode
tekin16:cmp tekident,0 ; just identifying?
jne tekin16a ; ne = yes
cmp inited,0 ; inited yet?
jne tekin19 ; ne = yes, restore screen
mov ttstate,offset tektxt ; do displayable text
mov prestate,offset tektxt ; set a previous state of text
mov inited,1 ; say we have initialized
jmp short tekin16b ; and init the color palette
tekin16a:mov si,offset colpal ; active color palette
cmp havepal,0 ; have a color palette yet?
jne tekin17 ; yes, use active palette
tekin16b:mov si,offset mondef ; default monochrome colors
cmp plotptr,offset pltcga ; using CGA style graphics?
je tekin17 ; e = yes
cmp graph_mode,mono ; pure mono text system?
je tekin17 ; e = yes
cmp graph_mode,monoega ; ega, but monochrome?
je tekin17 ; e = no
mov si,offset coldef ; use color palette
tekin17:mov havepal,1 ; say have a color palette
mov al,[si+7] ; foreground color = palette 7
mov gfcol,al
mov al,[si] ; background color = palette 0
mov gbcol,al
mov cx,16
mov di,offset colpal ; VT340 active color palette
push es
push ds
pop es
cld
rep movsb ; reinit palette entries
pop es
call fixcolor ; correct color mapping for some bds
mov al,gfcol
mov tfcol,al ; remember current coloring
mov al,gbcol
mov tbcol,al
cmp tekident,0 ; just identifying?
jne tekin21 ; ne = yes
call tekcls ; clear screen, for ega coloring
jmp short tekin20
tekin19:cmp vtclear,0 ; clear screen?
je tekin19a ; e = no
call tekcls ; clear screen, use existing colors
jmp short tekin20
tekin19a:call tekrest ; restore old graphics screen
mov al,tfcol ; and coloring
mov gfcol,al
mov al,tbcol
mov gbcol,al
tekin20:call setcursor ; set text cursor, if any
mov ax,250
call tekwait ; 250 ms wait for display adapter
mov ax,flow ; get flow control word
xchg ah,al ; get xon into al
or al,al ; able to send xon?
jz tekin21 ; z = no
call outmodem ; tell host xon
tekin21:mov al,chcontrol ; opaque/transparent char writing
mov bscontrol,al ; set destructive BS control
mov spcontrol,al ; set destructive SPACE control
mov tekident,0
mov bypass,0 ; clear Bypass flag
clc ; clear carry for success
pop es
pop di
pop si
pop dx
pop cx
pop bx
pop ax
ret
tekini endp
TEKRINT proc far ; Tek reinitialization entry point
call dword ptr endptr ; exit cleanly if alread in Tek mode
xor ax,ax ; get a null
mov inited,al ; do complete reinitialization
mov tekflg,al
mov xcenter,ax ; forget center of screen
mov ycenter,ax
call tekini
ret
TEKRINT endp
; End TEK emulation, recover previous screen
TEKEND proc far
mov ttstate,offset tektxt ; set an initial state
mov prestate,offset tektxt ; and a previous state
test tekflg,1 ; running as a Tek terminal now?
jnz teknd1 ; nz = yes
mov tekflg,0 ; returning to text emulator
ret ; else return as is
teknd1: call remcursor ; remove text cursor, if any
call teksave ; save graphics screen to page 1
cmp graph_mode,hercules ; Hercules?
jne teknd2 ; ne = no
call htext ; yes then set up Hercules text mode
teknd2: call mousexit ; restore mouse state, if any
xor ah,ah ; set video mode
mov al,curmode ; restore previous screen mode
int screen ; revert to text screen
call trestscr ; restore text screen
mov dx,cursor ; saved cursor position
xor bh,bh ; page 0
mov ah,2 ; set cursor
int screen
mov tekflg,0 ; returning to text emulator
mov lastc,0
mov bypass,0 ; reset bypass condition
mov visible,0 ; next move is invisible
clc
ret
TEKEND ENDP
;Terminal emulation. Enter with received character in AL.
TEKEMU proc far ; main emulator
call tektt ; local emulator routine
ret
TEKEMU endp
tektt proc near
test tekflg,1 ; running as a Tek device?
jnz tektt1 ; nz = yes
push ax
call tekini ; init now
pop ax
mov ttstate,offset tektxt ; initial state
mov prestate,offset tektxt ; set a previous state of text
jnc tektt1 ; nc = succeeded
ret ; else failed to init, just return
tektt1: test al,80h ; high bit set?
jz tektt1a ; z = no
cmp al,9fh ; in range for C1 controls?
ja tektt1a ; a = no
push ax ; save the char
mov al,escape ; make 7-bit control version
call tektt2 ; act on escape
pop ax
sub al,40h ; get second char of 7-bit control
tektt1a:and al,7fh ; force Tek chars to be 7 bits
or al,al ; NUL char?
jnz tektt2 ; nz = no
ret ; yes, ignore it (before logging)
tektt2: test yflags,capt ; capturing output?
jz tektt4 ; z = no, forget this part
push ax ; save char
call tcptchr ; give it captured character
pop ax ; restore character and keep going
tektt4: test yflags,trnctl ; debug? if so use tty mode
jz tektt5 ; z = no
cmp al,DEL ; DEL char?
jne tektt4a ; ne = no
mov al,5eh ; make DEL a caret query mark
call outscrn
mov al,3fh ; the query mark
call outscrn
ret
tektt4a:cmp al,' ' ; control char?
jae tektt4b ; ne = no
push ax
mov al,5eh ; caret
call outscrn
pop ax
add al,'A'-1 ; make char printable
tektt4b:call outscrn
ret
tektt5: cmp bypass,0 ; Bypass mode off?
jne tektt5a ; ne = no, on, ignore all incoming
call ttstate ; do current state
ret
tektt5a:cmp al,' ' ; incoming control code?
jae tektt5b ; ae = no
mov bypass,0 ; turn off bypass
call ttstate ; act on it
tektt5b:ret
tektt endp
TEKTXT proc near ; Dispatch on text characters
mov ttstate,offset tektxt ; this is our state
push ax
call setcursor ; show text cursor
pop ax
cmp al,DEL ; RUBOUT?
jne tektx1 ; ne = no
mov al,bs ; make BS
jmp short tektx7
tektx1: cmp al,CR ; carriage return (^M)?
je tektx7 ; e = yes
cmp al,LF ; line feed (^J)?
je tektx7 ; e = yes
cmp al,FF ; form feed (^L)?
jne tektx4 ; ne = no
call tekcls ; clear the screen
ret
tektx4: cmp al,VT ; vertical tab (^K)?
je tektx7
cmp al,bell ; bell (^G)?
jne tektx5 ; ne = no
call tekbeep
ret
tektx5: cmp al,tab ; horizontal tab (^I)?
je tektx7 ; e = yes
cmp al,BS ; backspace (^H)?
je tektx7 ; e = yes
cmp al,' ' ; control char?
jae tektx7 ; ae = no
jmp tekctl ; process control char
tektx7: call outscrn ; output character to the screen
tektx8: ret
TEKTXT endp
tekctl proc near ; Control characters:
cmp al,GS ; Line plot command?
jne tekctl1 ; ne = no
mov visible,0 ; next move is invisible
and status,not txtmode ; set status report byte
mov ttstate,offset tekline ; expect coordinates next
call remcursor ; remove text cursor
ret
tekctl1:cmp al,RS ; Incremental dot command?
jne tekctl2 ; ne = no
and status,not txtmode ; set status report
mov ttstate,offset tekrlin ; expect pen command next
call remcursor ; remove text cursor
ret
tekctl2:cmp al,FS ; Point plot command?
jne tekctl3 ; ne = no
mov visible,0 ; next move is invisible
and status,not txtmode ; set status report byte
mov ttstate,offset tekpnt
call remcursor ; remove text cursor
ret
tekctl3:cmp al,US ; assert text mode? [bjh]
jne tekctl4 ; ne = no
or status,txtmode ; set status report byte
mov ttstate,offset tektxt ; go to TEKTXT next time
mov visible,0 ; next move is invisible
call setcursor ; restore text cursor
ret
tekctl4:cmp al,ESCAPE ; Escape?
jne tekctl5 ; ne = no
call remcursor ; remove text cursor
or status,txtmode ; set status report byte
cmp ttstate,offset tekesc ; already in escape state?
je tekctl7 ; e = yes, nest no further
push ttstate ; current state
pop prestate ; save here as previous state
mov ttstate,offset tekesc ; next state parses escapes
ret
tekctl5:cmp al,CAN ; Control X? (exits Tek sub mode)
jne tekctl7 ; ne = no, stay in current state
mov ttstate,offset tektxt ; back to text mode
mov bypass,1 ; turn on bypass mode
cmp flags.vtflg,tttek ; main Tek emulator?
je tekctl6 ; e = yes, ignore the ^X
call tekend ; else exit sub mode
mov visible,0 ; next move is invisible
tekctl6:mov prestate,offset tektxt ; make previous state text
tekctl7:ret
tekctl endp
TEKESC proc near ; Process ESC <following text>
mov ninter,0 ; initialize parsing
mov ttstate,offset tekesc ; in case get here from msz file
cmp inited,0 ; inited yet? (msz call)
jne tekesc1 ; ne = yes
call tekini ; init now
mov prestate,offset tektxt ; set a previous state of text
jnc tekesc1 ; nc = succeeded
ret ; else failed to init, just return
tekesc1:cmp al,20h ; in intermediates, column 2?
jb tekesc3 ; b = no
cmp al,2fh
ja tekesc3 ; a = no
mov ttstate,offset tekesc1 ; stay in this state while intermeds
mov bx,ninter ; number of intermediates
cmp bx,maxinter ; done enough already?
jae tekesc2 ; ae = yes, ignore the excess
mov inter[bx],al ; store this one
inc ninter ; one more
cmp inter,'/' ; HDS2000/3000 Final char?
je tekesc3 ; e = yes, process specially like '['
tekesc2:ret ; get more input
; Final char is in AL, dispatch on it
tekesc3:mov ttstate,offset tektxt ; set new state
mov esctype,al ; save kind of escape sequence
mov bx,offset esctab ; ESC dispatch table
call atdispat ; dispatch on AL
ret
TEKESC endp
tekeseq proc near ; process Escape and Device Contrl seq
call tparstart ; init escape sequence parser
mov ttstate,offset escparse ; do parsing next
ret
tekeseq endp
; State for gathering text to feed escape sequence parser
escparse proc near
cmp al,' ' ; embedded control code?
jb escpar2 ; b = yes, process now
call tparser ; far call, to call real parser
jnc escpar1 ; nc = success
push prestate ; recover previous state
pop ttstate
stc
escpar1:ret
escpar2:call tekctl ; process embedded control code
push prestate ; get previous state
pop ttstate ; restore it
ret
escparse endp
; Escape sequence parser completion routine
; AL has Final character of escape sequence
XPARDONE PROC FAR ; called by tpardone when done
cmp esctype,'[' ; ansi escape sequence (ESC [)?
jne xpardo3 ; ne = no
mov bx,offset anstab ; ANSI ESC [ table
call atdispat ; dispatch on Final char in AL
jmp short xpardo5
xpardo3:cmp esctype,'/' ; HDS escape sequence (ESC /)?
jne xpardo4 ; ne = no
call hdsesc ; analyze
jmp short xpardo5
xpardo4:cmp esctype,'P' ; DCS introducer?
jne xpardo5 ; ne = no
call tekdcs ; grab parameters etc, prep strings
ret
xpardo5:push prestate ; recover previous state
pop ttstate
ret
XPARDONE ENDP
; ESC <char> action routines
; exit each by putting prestate into ttstate
tekenq proc near ; ESC-^E Enquiry for cursor position
mov bypass,1 ; set bypass mode
call sendstat ; send status
push prestate ; get previous state
pop ttstate ; restore it
ret
tekenq endp
tekcan proc near ; ESC ^X
push prestate ; get previous state
pop ttstate ; restore it
jmp tekctl ; process in controls section
tekcan endp
tekgin proc near ; ESC-^Z Enter GIN mode
cmp graph_mode,mono ; Monochrome text mode?
je tekgin1 ; e = yes, no crosshairs in text mode
mov bypass,1 ; turn on GIN mode bypass conditon
call crossini ; preset crosshairs
call croshair ; activate the cross-hairs
jmp short tekgin2
tekgin1:call tekbeep ; tell the user we are unhappy
tekgin2:push prestate ; get previous state
pop ttstate ; restore it
ret
tekgin endp
tektwo proc near ; ESC 2 (Exit Tek mode)
mov al,CAN ; force Control-X
jmp tekcan ; process there as ESC ^X
tektwo endp
tekqury proc near ; query mark (ESC ? means DEL)
mov al,DEL ; replace with DEL code
push prestate ; get previous state
pop ttstate ; restore it
ret
tekqury endp
tekfill proc near ; Fill series ESC @ .. ESC M
sub al,'@' ; remove bias
mov bl,al
xor bh,bh
shl bx,1 ; make a word index
mov bx,fillist[bx] ; get pointer to the pattern from list
mov fillptr,bx ; assign this pattern pointer
push prestate ; get previous state
pop ttstate ; restore it
ret
tekfill endp
teklpat proc near ; ESC accent grave line pattern series
cmp al,'g' ; accent ... lowercase g?
jbe teklpa2 ; be = yes
cmp al,'o' ; bold patterns ESC h..ESC o?
ja teklpa1 ; a = no
sub al,'h'-accent ; map bold to normal
jmp short teklpa2
teklpa1:sub al,'x'-'f' ; user sets,map x to f, y to g, z to h
teklpa2:push bx
mov bl,al
sub bl,accent ; remove bias
cmp bl,8 ; nine patterns, ignore others
jbe teklpa3 ; be = ok, make others accent, solid
xor bl,bl ; solid pattern
teklpa3:xor bh,bh
shl bx,1 ; make this a word index
mov bx,linetab[bx] ; get line pattern word
mov linepat,bx ; save in active word
pop bx ; return to previous mode
push prestate ; get previous state
pop ttstate ; restore it
ret
teklpat endp
; Detect exit Tek submode command ESC [ ? 38 l from VT340's
escexit proc near
cmp lparam,'?' ; possible "ESC [ ? 38 l"?
jne escex2 ; ne = no
cmp nparam,1 ; just one numeric parameter?
jne escex2 ; ne = no
cmp al,'l' ; ESC [ ? Pn l?
jne escex4 ; ne = no, try 'h'
cmp param,38 ; correct value?
jne escex3 ; ne = no
cmp flags.vtflg,tttek ; are we a full Tek terminal now?
je escex1 ; e = yes, stay that way
call dword ptr endptr ; call far tekend
ret
escex1: mov ttstate,offset tektxt
mov al,CAN ; simulate arrival of Control-X
jmp tektxt ; process char as text
escex2: ret
escex3: cmp param,34 ; ESC [ ? 34 l?
jne escex2 ; ne = no
call tekend ; play safe and restore text mode
xor ax,ax ; tell tekmac it's a Reset flavor
call tekmac ; returns only if successful
ret
escex4: cmp al,'h' ; ESC ... h?
jne escex3 ; ne = no
cmp param,34 ; ESC [ ? 34 h?
jne escex2 ; ne = no
call tekend ; play safe and restore text mode
mov ax,1 ; tell tekmac it's a Set flavor
call tekmac ; returns only if successful
ret
escexit endp
; Human Data Systems 2000/3000 style escape sequences (ESC / params Final)
; Final character is in AL
hdsesc proc near
cmp al,'x' ; draw an empty rectangle?
jne hdsesc0 ; ne = no
call rectdraw
jmp short hdsesc2a
hdsesc0:cmp al,'y' ; draw a filled rectangle?
jne hdsesc1 ; ne = no
call rectfil ;do xhome,yhome,xwidth,yheight,pattern
jmp short hdsesc2a
hdsesc1:cmp al,'z' ; draw and fill rectangle?
jne hdsesc2 ; ne = no
call rectfil ; do fill before border
call rectdraw ; do border
jmp short hdsesc2a
hdsesc2:cmp ninter,0 ; any intermediates?
jne hdsesc2a ; ne = yes, failure
cmp lparam,0 ; letter parameter?
jne hdsesc2a ; ne = yes, failure
cmp nparam,1 ; just zero or one numeric parameter?
ja hdsesc9 ; a = no
cmp al,'a' ; user defined pattern?
jb hdsesc3 ; b = no
cmp al,'c'
ja hdsesc3 ; a = no
sub al,'a' ; 'a' is first of three user patterns
xor ah,ah ; store as 'f,g,h' in the series
mov bx,ax
shl bx,1 ; make a word index
mov ax,param[0] ; get the 16-bit pattern
mov linetab[bx+12],ax ; store in user defined pattern
hdsesc2a:push prestate ; get previous state
pop ttstate ; restore it
ret
hdsesc3:cmp al,'d' ; "Data Level" (pixel ops)?
jne hdsesc4 ; ne = no
mov cx,param ; get the parameter value
mov al,pixfor ; assume foreground only ESC / 0 d
cmp cl,1 ; something else?
jb hdsesc3a ; b = no
mov al,pixbak ; assume background only ESC / 1 d
cmp cl,2 ; something else?
jb hdsesc3a ; b = no
mov al,pixxor ; assume XOR ESC / 2 d
cmp cl,3 ; something else?
jb hdsesc3a ; b = no
ja hdsesc3b ; a = unknown, ignore
mov al,pixfor+pixbak ; write both absolute ESC / 3 d
hdsesc3a:mov ccode,al ; use as pixel op coding
hdsesc3b:push prestate ; get previous state
pop ttstate ; restore it
ret
hdsesc4:cmp al,'h' ; set space, backspace control?
je hdsesc4a ; e = yes
cmp al,'l' ; reset space, backspace control?
jne hdsesc9 ; ne = no
xor ah,ah ; say resetting
jmp short hdsesc5
hdsesc4a:mov ah,1 ; say setting
hdsesc5:cmp param,2 ; space control?
jne hdsesc5a ; ne = no
mov spcontrol,ah ; reset (0) or set destructive SPACE
push prestate ; get previous state
pop ttstate ; restore it
ret
hdsesc5a:cmp param,9 ; destructive backspace?
jne hdsesc13 ; ne = no
mov bscontrol,ah ; reset (0) or set destructive BS
hdsesc9:cmp al,'C' ; user defined fill pattern #1?
jne hdsesc10 ; ne = no
mov di,offset filpat13 ; storage area for user pattern #1
jmp short hdsesc11
hdsesc10:cmp al,'D' ; user defined fill pattern #2?
jne hdsesc11 ; ne = no
mov di,offset filpat14 ; storage area for user pattern #2
hdsesc11:mov cx,8 ; do 8 paramters
xor bx,bx
hdsesc12:mov ax,param[bx] ; copy 8 bit fill pattern
mov [di],al ; to array
add bx,2
inc di
loop hdsesc12
hdsesc13:push prestate ; get previous state
pop ttstate ; restore it
ret
hdsesc endp
; Analyze ESC [ Pn ; Pn m color command
; where Pn = 30-37 foreground color, 40-47 background color, ANSI standard
; Enter with escape sequence already parsed.
TEKCOL proc near
push si
cld
mov al,gfcol ; update these in case error
mov tfcol,al
mov al,gbcol
mov tbcol,al
mov si,offset param ; parameters from parser
mov cx,nparam ; number of parameters
tekco1: jcxz tekco5 ; z = none left
lodsw ; parameter to ax
dec cx
or ax,ax ; 0, remove intensity, set b/w?
jnz tekco2 ; nz = no
mov tfcol,7 ; regular white
mov tbcol,0 ; on black
jmp short tekco1
tekco2: cmp ax,1 ; intensity bit?
jne tekco3 ; ne = no
or tfcol,8 ; set foreground intensity
jmp short tekco1
tekco3: cmp ax,30 ; foreground series?
jb tekco1 ; b = no
cmp ax,37
ja tekco4 ; a = no
sub ax,30 ; remove bias
push bx
mov bl,al
xor bh,bh
mov al,byte ptr colortb[bx] ; reverse coloring
pop bx
and tfcol,not (7) ; retain intensity bit
or tfcol,al ; remember foreground color
jmp short tekco1
tekco4: cmp ax,40
jb tekco1
cmp ax,47 ; legal value?
ja tekco1 ; a = no
sub al,40
push bx
mov bl,al
xor bh,bh
mov al,byte ptr colortb[bx] ; reverse coloring
pop bx
mov tbcol,al ; remember background color
jmp short tekco1
tekco5: cmp ninter,0 ; intermediates?
jne tekco7 ; ne = yes, no go
cmp lparam,0 ; letter parameter?
jne tekco7 ; ne = yes, no go
cmp nparam,0 ; number of ansi arguments, zero?
ja tekco6 ; a = no, got some
mov tbcol,0 ; none is same as 0, set b/w
mov tfcol,7
tekco6: mov al,tbcol ; success, store coloring
mov gbcol,al ; set background color
mov al,tfcol
mov gfcol,al ; set foreground color
call fixcolor ; do special ega corrections
mov al,gfcol ; update these in case error
mov tfcol,al
mov colpal[7],al ; foreground goes here
mov al,gbcol
mov tbcol,al
mov colpal[0],al ; background goes here
tekco7: pop si
clc
ret
TEKCOL endp
; Revise screen color codes for ega boards with mono displays and limited
; memory.
fixcolor proc near
cmp graph_mode,ega ; one of these ega modes?
je fixcol6 ; e = yes
cmp graph_mode,colorega
je fixcol6
cmp graph_mode,monoega
je fixcol6
cmp plotptr,offset pltcga ; using CGA style graphics?
jne fixcol5 ; ne = no
and gfcol,7 ; strip intensity
jmp short fixcol6 ; keep colors different
fixcol5:ret ; else ignore color corrections
fixcol6:mov ah,gfcol
mov al,gbcol
cmp graph_mode,monoega ; monochrome ega display?
jne fixcol3 ; ne = no
test al,7 ; bright backgound?
jnz fixcol1 ; nz = yes
mov ah,1 ; normal foreground
test gfcol,8 ; intensity on?
jz fixcol1 ; z = no
mov ah,5 ; say bright foreground
fixcol1:test al,7 ; black backgound?
jz fixcol2 ; z = yes
mov al,1 ; regular video
fixcol2:cmp ah,al ; same color in both?
jne fixcol3 ; ne = no
mov ah,1 ; make foreground regular
xor al,al ; and background black
fixcol3:mov gfcol,ah
mov gbcol,al
cmp gpage,0 ; minimal memory (64KB mono and ega)?
ja fixcol4 ; a = no, enough, else strange mapping
mov al,gfcol ; fix coloring to map planes C0 to C1
and al,5 ; and C2 to C3 (as 0, 3, 0Ch, or 0Fh)
mov ah,al ; make a copy
shl ah,1 ; duplicate planes C0, C2 in C1, C3
or al,ah ; merge the bits
mov gfcol,al ; store proper foreground color
mov al,gbcol ; repeat for background color
and al,5
mov ah,al
shl ah,1
or al,ah
mov gbcol,al
fixcol4:ret
fixcolor endp
tekrid proc near ; report Tek screen parameters
cmp lparam,'?' ; possible "ESC [ ? 38 l"?
jne tekridx ; ne = no
cmp nparam,1 ; just one numeric parameter?
jne tekridx ; ne = no
cmp param,256 ; correct value?
je tekrid1 ; e = yes
tekridx:ret
tekrid1:push es ; as ESC [ ? 256; height; len; #col n
push ds
pop es
cld
mov di,offset tempname ; a temp buffer
mov al,escape ; report
stosb
mov al,'['
stosb
mov al,'?'
stosb
mov ax,256
call dec2di ; write ascii digits
mov al,';'
stosb
mov ax,ybot ; do height
inc ax
cmp graph_mode,mono ; pure mono text system?
jne tekrid7a ; ne = no
mov ax,24
tekrid7a:call dec2di
mov al,';' ; separator
stosb
mov ax,xmax ; width
add ax,8 ; in dots
cmp graph_mode,mono ; pure mono text system?
jne tekrid7b ; ne = no
mov ax,80
tekrid7b:call dec2di
mov al,';' ; separator
stosb
mov al,'1' ; screen colors, assume 1
stosb
cmp plotptr,offset pltcga ; using CGA style graphics?
je tekrid4 ; e = yes
cmp graph_mode,monoega ; monochrome monitor on ega?
je tekrid4 ; e = yes
cmp graph_mode,mono ; pure mono text system?
jne tekrid3
mov byte ptr [di-1],'0' ; say zero colors
jmp short tekrid4
tekrid3:mov al,'6'
stosb ; say 16
tekrid4:mov al,'n' ; end of string
stosb
call outstrng ; send the string
pop es
ret
tekrid endp
tekprpt proc near
cmp nparam,1 ; one or more numeric parameters?
jb tekrprx ; b = no
cmp param,2 ; "CSI 2 $ u"?
jne tekrprx ; ne = no
cmp inter,'$' ; correct Intermediate?
jne tekrprx ; ne = no
call dword ptr rptptr ; invoke the palette report generator
tekrprx:ret
tekprpt endp
tekrpt proc FAR ; report VT340 color palette
push es ; DECRQTSR(request), DECCTR(response)
push ds
pop es
push di
push bx
cld
mov di,offset tempname ; a temp buffer
mov al,escape ; report
stosb
cmp plotptr,offset pltcga ; using CGA style graphics?
je tekrpt9 ; e = yes
cmp graph_mode,mono ; pure mono text system?
je tekrpt9 ; e = yes
cmp graph_mode,monoega ; monochrome monitor on ega?
jne tekrpt10 ; ne = no
tekrpt9:mov ax,'0P' ; b/w systems report DCS 0 $ s ST
stosw
mov ax,'s$'
stosw
call outstrng
jmp tekrpt8
tekrpt10:mov ax,'2P' ; color systems report DCS 2 $ s...ST
stosw
mov ax,'s$'
stosw ; "ESC [ 2 $ s"
call outstrng ; output this string
mov cx,16 ; number of palette registers to do
xor bx,bx ; begin with color palette 0
tekrpt1:push bx ; save palette index
push cx ; save loop counter
mov di,offset tempname ; buffer
mov ax,bx ; palette number
call dec2di ; palette register, to buffer
mov ax,'2;' ; ";2;" means sending RGB values
stosw
mov al,';'
stosb
mov ah,colpal[bx] ; get palette iRGB
mov al,rgbbold/4 ; assume dark red for bold black
cmp ah,8 ; bold black?
je tekrpt2 ; e = yes
xor al,al
test ah,4 ; red?
jz tekrpt2 ; z = no
mov al,rgbbold/2 ; say red, 40%
test ah,8 ; bold?
jz tekrpt2 ; z = no
mov al,rgbbold ; more if bold
tekrpt2:push ax
xor ah,ah ; clear high byte
call dec2di ; store red
pop ax
mov al,';' ; separator
stosb
mov al,rgbbold/4 ; assume dark green for bold black
cmp ah,8 ; bold black?
je tekrpt4 ; e = yes
xor al,al
test ah,2 ; green?
jz tekrpt4 ; z = no
mov al,rgbbold/2 ; say green, 40%
test ah,8 ; bold?
jz tekrpt4 ; z = no
mov al,rgbbold ; more if bold
tekrpt4:push ax
xor ah,ah ; clear high byte
call dec2di ; store green
pop ax
mov al,';' ; separator
stosb
mov al,rgbbold/4 ; assume dark blue for bold black
cmp ah,8 ; bold black?
je tekrpt6 ; e = yes
xor al,al
test ah,1 ; blue?
jz tekrpt6 ; z = no
mov al,rgbbold/2 ; say blue, 40%
test ah,8 ; bold?
jz tekrpt6 ; z = no
mov al,rgbbold ; more if bold
tekrpt6:xor ah,ah ; clear high byte
call dec2di ; store blue
pop cx ; recover loop counter
cmp cx,1 ; doing last item?
je tekrpt7 ; e = yes, do not send another "/"
mov al,'/' ; separator
stosb
tekrpt7:push cx
call outstrng ; output this string
pop cx
pop bx ; recover palette index
inc bx ; ready for next palette
dec cx
jz tekrpt8 ; z = done
jmp tekrpt1 ; do all palettes
tekrpt8:mov al,escape ; DCS terminator ST
call outmodem
mov al,'\'
call outmodem
pop bx
pop di
pop es
ret
tekrpt endp
; Output string in tempname. Enter with di pointing at last byte+1. Return
; with di at the same place.
outstrng proc near
mov ttyact,0 ; group output for network
push cx
mov cx,di ; compute length
mov di,offset tempname ; start of buffer
sub cx,di ; start of buffer
jle outstn3 ; le = nothing to do
outstn1:mov al,[di]
inc di
cmp cx,1 ; last character?
ja outstn2 ; a = no
mov ttyact,1 ; end group output for network
outstn2:call outmodem ; send the byte
loop outstn1 ; do the string
outstn3:pop cx
ret
outstrng endp
; Process Device Control Strings (DCS or ESC P lead-in chars, parameters,
; and Final character already read). Prepare to gather strings.
tekdcs proc near
mov dcsstrf,al ; record Final char
mov emubufc,0 ; clear string count
mov cx,maxparam ; number of DCS parameters
push si ; copy these to the DCS area so that
push di ; they are not lost when an ST is
push es ; parsed (parser clears ESC items)
push ds
pop es
mov si,offset param ; ESC paramater storage area, numeric
mov di,offset dparam ; DCS parameter storage area, numeric
cld
rep movsw ; copy set to DCS storage area
mov cl,lparam ; copy letter Paramter
mov dlparam,cl
mov cx,maxinter ; number of intermediate characters
mov si,offset inter ; source
mov di,offset dinter ; destination
rep movsb
mov si,nparam ; number of parameters
mov dnparam,si
mov si,ninter
mov dninter,si ; number of intermediates
pop es
pop di
pop si
cmp dcsstrf,'q' ; Sixel Graphics?
jne tekdcs3 ; ne = no
mov ttstate,offset tekgets ; get string as next state
mov al,chcontrol ; opaque/transparent char writing
or al,al ; is it being set?
jz tekdcs2 ; z = no, do not force condition
mov bscontrol,al ; set destructive BS control
mov spcontrol,al ; set destructive SPACE control
tekdcs2:ret
tekdcs3:cmp dcsstrf,'p' ; restore color palette (DCS 2 $ p)?
jne tekdcs1 ; ne = no
cmp nparam,1 ; just one parameter?
jne tekdcs1 ; ne = no
cmp param,2 ; correct parameter?
jne tekdcs1 ; ne = no
cmp dinter,'$' ; correct intermediate?
jne tekdcs1 ; ne = no
mov ttstate,offset tekrcol ; get color report as next state
ret
tekdcs1:mov ttstate,offset tekdcsnul ; consume unknown DCS
ret
tekdcs endp
; Read and discard OSC (ESC ]), PM (ESC ^), APC (ESC _) control sequences
; through final ST (ESC \) terminator.
tekdcsnul proc near
mov dcsstrf,0 ; simulate a null (dummy) Final char
cmp al,20h ; control char?
jae tekdcsnu1 ; ae = no, skip
jmp tekctl ; do control char
tekdcsnu1:ret
tekdcsnul endp
; State machine to process DCS strings of type "p" (restore color palette)
; Enter with "p" char in AL. Callable from outside this file via tekrpal.
tekrcol proc near
mov ttstate,offset tekrco1 ; next state is get parameter
push ax ; save character
push es
push ds
pop es
push di
mov cx,5 ; five words
xor ax,ax
mov di,offset param ; clear parameters Pc,Pu,Px,Py,Pz
cld
rep stosw
pop di
pop es
mov nparam,0 ; work on initial parameter first
pop ax
tekrco1:cmp al,escape ; escape, as in ESC \?
je tekrcost ; e = yes, finish command
cmp al,' ' ; control code?
jb tekrco5 ; b = yes, ignore it
push bx
mov bx,nparam ; parameter number
shl bx,1 ; make it a word index
mov cx,param[bx] ; accumulated parameter
call getdec ; accumulate decimal value
mov param[bx],cx ; remember accumulation
pop bx
jnc tekrco5 ; nc = got a digit char
inc nparam ; say have another complete parameter
cmp al,'/' ; this kind of separator?
je tekrco3 ; e = yes, finish
cmp al,';' ; break char is separator?
jne tekrco4 ; ne = no, decode current sequence
tekrco3:cmp nparam,5 ; have 5 params already?
jb tekrco5 ; n = no, continue reading
tekrco4:call tekgco4 ; process parameters in msgibm file
mov ttstate,offset tekrcol ; next state is get parameter
tekrco5:ret ; start over on next field
tekrcost: ; get here on ST
cmp nparam,5 ; enough parameters to finish cmd?
jb tekrcos1 ; b = no, abandon it
call tekgco4 ; update from last data item
mov al,escape
tekrcos1:jmp tekctl
tekrcol endp
; State machine to process DCS strings of type "q" (Sixel Command and Data)
; Enter with new char in AL.
tekgets proc near
mov ttstate,offset tekgets ; set state to ourselves
mov nparam,0 ; say no pending control sequences
cmp al,20h ; control character?
jae tekgsch ; ae = no, analyze
jmp tekctl ; do control char
; single sixel char state
tekgsch:cmp al,3fh ; legal sixel data char?
jb tekgrpt ; b = no, try repeated char
mov cx,1 ; repeat count of 1
jmp sixplt ; plot the six dots
tekgrpt:cmp al,'!' ; repeated char?
jne tekgera ; ne = no
mov ttstate,offset tekgrpt0 ; next state is get repeat parameter
mov param,0
mov nparam,0
ret
tekgrpt0:cmp al,' ' ; control char?
jae tekgrpt1 ; ae = no
jmp tekctl ; process control char
tekgrpt1:mov cx,param ; first param is used here
call getdec ; accumulate repeat count to cx
mov param,cx ; retain current count
jc tekgrpt2 ; c = ended on non-numeric
ret ; get more characters
tekgrpt2:cmp al,3fh ; break char, is it a sixel datum?
jb tekgrpt3 ; b = no, it is illegal, quit
call sixplt ; plot cx versions of the six bits
mov ttstate,offset tekgets ; return to sixel idle state
ret
tekgrpt3:jmp short tekgets ; reprocess break character
tekgera:cmp al,22h ; double quote raster attribute?
jne tekgco ; ne = no, try color
mov param,0 ; clear parameters, Pan
mov param[2],0 ; Pad
mov param[4],0 ; Ph
mov param[6],0 ; Pv
mov nparam,0 ; work on initial parameter first
mov ttstate,offset tekgra1 ; next state is get parameter
ret
tekgra1:cmp al,' ' ; control char?
jb tekgra2 ; b = yes, finish this work first
push bx
mov bx,nparam ; parameter number
shl bx,1 ; make it a word index
mov cx,param[bx] ; accumulated parameter
call getdec ; accumulate decimal value into cx
mov param[bx],cx ; remember accumulation
pop bx
jc tekgra2 ; c = failure to get a digit char
ret
tekgra2:inc nparam ; say have another complete parameter
cmp nparam,4 ; got all four params Pan,Pad,Ph,Pv?
je tekgra4 ; e = yes
cmp al,';' ; break char is separator?
jne tekgra3 ; ne = no, quit now
ret ; get more characters
tekgra3:jmp tekgets ; restart with the break char
tekgra4:;;; perform raster attributes work here
mov ttstate,offset tekgets
ret
tekgco: cmp al,'#' ; color introducer?
je tekgco0 ; e = yes
jmp tekgcr ; ne = no
tekgco0:mov ttstate,offset tekgco1 ; next state is get parameter
push ds
pop es
push di
mov cx,5 ; five words
xor ax,ax
mov di,offset param ; clear parameters Pc,Pu,Px,Py,Pz
cld
rep stosw
pop di
pop es
mov nparam,0 ; work on initial parameter first
ret
tekgco1:cmp al,' ' ; control char?
jb tekgco2 ; b = yes, finish this work first
push bx
mov bx,nparam ; parameter number
shl bx,1 ; make it a word index
mov cx,param[bx] ; accumulated parameter
call getdec ; accumulate decimal value
mov param[bx],cx ; remember accumulation
pop bx
jc tekgco2 ; c = failure to get a digit char
ret
tekgco2:inc nparam ; say have another complete parameter
cmp al,';' ; break char is separator?
jne tekgco3 ; ne = no, decode current sequence
cmp nparam,5 ; have 5 params already?
jae tekgco3 ; ae = yes, process them now
ret ; else get more parameters
tekgco3:cmp nparam,1 ; just one parameter?
je tekgco3a ; e = yes, select from palette
jb tekgco3b ; b = none, reprocess as sixel
call tekgco4 ; process parameters
mov nparam,0 ; clear parameters
jmp tekgets ; reprocess char as sixel
tekgco3a:push bx ; select color from palette
mov bx,param[0] ; get color number
xor bh,bh ; make 0-255
mov bl,colpal[bx] ; get color from palette
mov gfcol,bl ; set active foreground color
pop bx
push ax ; save char in al
call fixcolor ; fix color too, if req'd
pop ax
tekgco3b:mov nparam,0 ; clear parameters
jmp tekgets ; reprocess char as sixel
; set IRGB/HLS color to color palette
tekgco4:cmp param[2],2 ; Pu (1-2), wanted RBG?
je tekgco4b ; e = yes
cmp param[2],1 ; Pu, wanted HLS?
jne tekgco4a ; ne = no
jmp tekgco9 ; do HLS scheme
tekgco4a:mov nparam,0 ; clear parameters
ret ; return without doing work
tekgco4b:push ax ; iRGB, save break char in al
mov ax,param[4] ; red
mov bx,param[6] ; green
mov dx,param[8] ; blue
xor cx,cx ; cl has final color index, 0-15
or ch,al
or ch,bl
or ch,dl ; any color?
jcxz tekgco7 ; z = no, use cl = 0 black
cmp ax,rgbbold ; setting red bold?
jae tekgco4c ; ae = yes
cmp bx,rgbbold ; setting green bold?
jae tekgco4c ; ae = yes
cmp dx,rgbbold ; setting blue bold?
jb tekgco4d ; b = no
tekgco4c:mov cl,8 ; set the bold bit
jmp tekgco4e ; do hues
tekgco4d:cmp ax,rgbbold/2 ; all in dim intensities?
jae tekgco4e ; ae = no
cmp bx,rgbbold/2 ; green?
jae tekgco4e ; ae = no
cmp dx,rgbbold/2 ; blue
jae tekgco4e ; ae = no
mov cl,8 ; use bold black (dark grey)
jmp tekgco7
tekgco4e:or ax,ax ; Hues, any red?
jz tekgco5 ; z = no
or cl,4 ; set red bit
cmp ax,rgbbold/2 ; dim?
jae tekgco5 ; ae = no
test cl,8 ; doing bold?
jz tekgco5 ; z = no
xor cl,4 ; clear dim red
tekgco5:or bx,bx ; any green?
jz tekgco6 ; z = no
or cl,2 ; set green bit
cmp bx,rgbbold/2 ; dim?
jae tekgco6 ; ae = no
test cl,8 ; doing bold?
jz tekgco6 ; z = no
xor cl,2 ; clear dim green
tekgco6:or dx,dx ; any blue?
jz tekgco7 ; z = no
or cl,1 ; set blue bit
cmp dx,rgbbold/2 ; dim?
jae tekgco7 ; ae = no
test cl,8 ; doing bold?
jz tekgco7 ; z = no
xor cl,1 ; clear dim blue
tekgco7:push bx
mov bx,param[0] ; Pc, color palette being defined
xor bh,bh ; make 0-255
mov colpal[bx],cl ; store color code in palette
pop bx
mov nparam,0 ; say done with this sequence
pop ax ; recover break char in al
ret
; Hue, Lightness, Saturation
tekgco9:push ax ; save break char
xor cl,cl ; assummed color of black
mov ax,param[4] ; Px, Hue, 60 degree slices
push cx
mov cx,360 ; do modulo 360
xor dx,dx ; clear high order numerator
div cx ; dx has remainder
pop cx
mov ax,dx ; put remainder in ax
cmp ax,30 ; blue?
jae tekgco10 ; ae = no
or cl,1 ; blue
jmp short tekgco15
tekgco10:cmp ax,90 ; magenta?
jae tekgco11 ; ae = no
or cl,1+4 ; magenta = blue + red
jmp short tekgco15
tekgco11:cmp ax,150 ; red?
jae tekgco12 ; ae = no
or cl,4 ; red
jmp short tekgco15
tekgco12:cmp ax,210 ; yellow?
jae tekgco13 ; ae = no
or cl,4+2 ; yellow = reg + green
jmp short tekgco15
tekgco13:cmp ax,270 ; cyan?
jae tekgco14 ; ae = no
or cl,2+1 ; cyan = green+blue
jmp short tekgco15
tekgco14:or cl,1 ; blue
tekgco15:mov ax,param[6] ; Py, Lightness
mov dx,param[8] ; Pz, Saturation
cmp ax,86 ; lightness is max?
jb tekgco16 ; b = no
mov cl,0fh ; greater than 85% means bold white
jmp short tekgco22
tekgco16:cmp ax,71 ; high lightness?
jb tekgco17 ; b = not that light
or cl,8 ; turn on bold bit
cmp dx,51 ; saturated?
jae tekgco22 ; ae = yes
mov cl,0fh ; low saturation yields bold white
jmp short tekgco22
tekgco17:cmp ax,57 ; central coloring, upper?
jb tekgco18 ; b = no
or cl,8 ; turn on bold bit
cmp dx,51 ; saturated?
jae tekgco22 ; ae = yes, use bold colors
mov cl,7 ; s < 50 is dim white
cmp dx,11 ; saturated less than 11%
jae tekgco22 ; ae = no
xor cl,cl ; s < 11 is black here
jmp short tekgco22
tekgco18:cmp ax,43 ; dim colors, upper?
jb tekgco19 ; b = no
or cl,8 ; turn on bold bit
cmp dx,51 ; saturated?
jae tekgco22 ; ae = yes, use bold colors
and cl,not 8 ; use dim colors
jmp short tekgco22
tekgco19:cmp ax,29 ; dim colors, lower?
jb tekgco20 ; b = no
cmp dx,51 ; saturated?
jae tekgco22 ; ae = yes
mov cl,7 ; use dim white
jmp short tekgco22
tekgco20:cmp ax,14 ; dark colors?
jb tekgco21 ; b = no
cmp dx,51 ; saturated?
jae tekgco22 ; ae = yes
tekgco21:xor cl,cl ; use black
tekgco22:push bx
mov bx,param[0] ; Pc, color palette being defined
xor bh,bh ; get palette 0-255
mov colpal[bx],cl ; store color code in palette
pop bx
mov nparam,0 ; say done with this sequence
pop ax ; recover break char
ret
tekgcr: cmp al,'$' ; graphics carriage return?
jne tekgnl ; ne = no
mov x_coord,0 ; go to left margin, no line feed
ret
tekgnl: cmp al,'-' ; graphics new line?
jne tekgunk ; ne = no
mov x_coord,0 ; go to left margin, no line feed
mov ax,y_coord ; bottom of char cell
add ax,6 ; go down 6 dots
cmp ax,ybot ; wrapping below bottom?
jbe tekgnl1 ; be = no
mov ax,ybot ; stop at bottom (leaves 2 dots free!)
tekgnl1:mov y_coord,ax
ret
tekgunk:mov ttstate,offset tekgets ; unknown char
cmp al,' ' ; control char?
jae tekgun1 ; ae = no
jmp tektxt ; process control char
tekgun1:ret ; ignore the unknown char
tekgets endp
; Accumulate decimal value in CX using ascii char in al.
; Return with value in CX. Return carry clear if ended on a digit,
; return carry set and ascii char in al if ended on a non-digit.
getdec proc near
cmp al,'0' ; a number?
jb getdecx ; b = no, quit
cmp al,'9'
ja getdecx ; a = not a number, quit
sub al,'0' ; remove ascii bias
xchg cx,ax ; put char in cx, decimal value in ax
push dx ; save reg
mul ten ; times ten for a new digit
pop dx ; recover reg, ignore overflow
add al,cl ; add current digit
adc ah,0 ; 16 bits worth
xchg ax,cx ; rpt cnt back to cx
clc ; say found a digit
ret
getdecx:stc ; say non-digit (in al)
ret
getdec endp
; Display lower six bits of AL in a column, a sixel datum. Do CX times.
; Location is PC text cursor, x_coord, y_coord, with least significant bit
; at the top (at y_coord-8). Increments x_coord by one for each interation
; but stops at right margin and does not change y_coord. If dparam[2], P2,
; is 1 then color pattern 0 bits in current background, else skip them.
sixplt proc near
or cx,cx ; repeat count present?
jnz sixplt1 ; nz = yes
ret
sixplt1:push ax
push bx
push linepat ; save line pattern
sub al,3fh ; remove ascii bias from sixel char
xor ah,ah
mov linepat,ax ; our dot pattern in lower 6 bits
mov di,y_coord ; text bottom cell line
sub di,8 ; go to top of 8 high char cell
jnc sixplt2 ; nc = no wrap over top
xor di,di ; limit to screen top
sixplt2:mov bx,di ; bx = ending y
add bx,5 ; plus our six dots (goes down screen)
cmp bx,ybot ; wrapping below bottom?
jbe sixplt3 ; be = no
mov bx,ybot ; stop at bottom
sixplt3:mov ax,x_coord ; left edge of text cell
mov si,ax ; si=starting, ax=ending PC x coord
add xmax,7 ; refer to right edge, not right char
push es ; set up for dot plotting, save regs
push si
push di
push dx
push bp
mov dl,ccode ; existing pixel op code
push dx ; save ccode around line drawing
mov ccode,pixor ; set OR pixel op for use by plot()
cmp gfcol,0 ; all black dots?
jne sixplt3a ; ne = no
mov ccode,pixfor ; yes, force overwriting to nulls
sixplt3a:push cx
call psetup ; setup display and es:di and es:si
pop cx
; start sixel repeat loop
sixplt4:push cx ; save sixel repeat count
push di ; save y starting screen address
mov bp,linepat ; store active line pattern word in BP
mov cx,6 ; six dots per sixel
; start six dot loop
sixplt5:push cx ; save dot count
mov cl,pixFor ; assume foreground coloring
test bp,1 ; bit to be plotted, is it a 1?
jnz sixplt6 ; nz = yes, plot in foreground color
cmp dparam[2],1 ; P2 = 1, skip over 0's?
je sixplt6 ; e = yes
mov cl,pixbak ; use background write pixel op
or bp,1 ; set pattern bit so we see a pixel
sixplt6:mov ccode,cl ; desired pixel op
call plotptr ; plot a dot if it is a 1
call pincy ; next dot down the screen (di)
pop cx ; recover dot counter
loop sixplt5 ; do each of 6 dots
;
pop di ; recover starting y screen coord
pop cx ; recover repeat count
cmp ax,xmax ; off right edge?
jae sixplt8 ; ae = yes
inc ax ; move right one pixel
inc si ; start and stop x's
sixplt8:loop sixplt4 ; repeat sixel cx times
pop dx
mov ccode,dl ; recover main color code
pop bp
pop dx
pop di
pop si
pop es
mov x_coord,ax ; new text starting x coord
sub xmax,7 ; restore to right most char cell
pop linepat ; restore normal line pattern
pop bx
pop ax
ret
sixplt endp
; Process ST or ESC \ String Terminator.
tekgotst proc near
mov dcsstrf,0 ; clear DCS Final char
mov nparam,0
mov ninter,0
mov al,colpal[7] ; reset foreground to palette 7
mov gfcol,al
mov al,colpal[0] ; and background to palette 0
mov gbcol,al
call fixcolor ; and fix up coloring, if req'd
mov prestate,offset tektxt ; reset state of emulator to normal
mov ttstate,offset tektxt
call setcursor ; restore text cursor
ret
tekgotst endp
TEKLINE proc near ; GS line drawing
cmp al,' ' ; control char?
jae teklin3 ; ae = no
cmp al,CR ; exit drawing on CR,LF,RS,US,FS,CAN
je teklin2 ; e = yes, a cr
cmp al,LF ; these terminate line drawing cmds
je teklin2
cmp al,FS ; <FS>
je teklin2
cmp al,GS ; <GS>
je teklin2
cmp al,RS ; <RS>
je teklin2
cmp al,US ; <US>
je teklin2
cmp al,CAN ; and <CAN>
je teklin2 ; BUT ignore other control chars
cmp al,escape ; escape?
je teklin1 ; e = yes, come back to this state
ret ; ignore stray control char
teklin1:jmp tekctl ; process control char
teklin2:mov lastc,0 ; clear last drawing coordinate flag
mov visible,0 ; invisible again
jmp tektxt ; process char under text mode
teklin3:call tekxyc ; parse coordinates from input bytes
jc teklin4 ; c = done, do the plotting
ret ; nc = not done yet
teklin4:mov cl,visible ; get moveto or drawto variable
call tekdraw ; move that point
mov visible,1 ; say next time we draw
ret
TEKLINE endp
TEKPNT proc near ; FS plot single point
cmp al,' ' ; control char?
jae tekpnt3 ; ae = no
cmp al,CR ; exit drawing on CR,LF,RS,US,FS,CAN
je tekpnt2 ; e = yes, a cr
cmp al,LF ; these terminate line drawing cmds
je tekpnt2
cmp al,FS ; <FS>
je tekpnt2
cmp al,GS ; <GS>
je tekpnt2
cmp al,RS ; <RS>
je tekpnt2
cmp al,US ; <US>
je tekpnt2
cmp al,CAN ; and <CAN>
je tekpnt2 ; BUT ignore other control chars
cmp al,escape ; escape?
je tekpnt1 ; e = yes
clc
ret ; ignore stray control char
tekpnt1:jmp tekctl ; process control char
tekpnt2:mov lastc,0 ; clear last drawing coordinate flag
mov visible,0 ; invisible again
jmp tektxt ; process char under text mode
tekpnt3:call tekxyc ; parse coordinates
jc tekpnt4 ; c = done, do the plotting
ret ; nc = not done yet
tekpnt4:xor cl,cl ; do not draw
call tekdraw ; move to the point
mov ax,si ; copy starting point to end point
mov bx,di ; ax,bx,si,di are in PC coordinates
mov cl,1 ; make plot visible
call line ; draw the dot
mov visible,0 ; return to invisibility
clc
ret
TEKPNT endp
; Decode graphics x,y components. Returns carry set to say have all
; components for a line, else carry clear. Understands 4014 lsb extensions.
; Permits embedded escape sequences.
TEKXYC proc near
cmp al,40h
jb tekgh2 ; 20-3F are HIX or HIY
cmp al,60h ; 40-5F are LOX (causes beam movement)
jb tekgh4 ; 60-7F are LOY
; extract low-order 5 bits of Y coord
mov ah,tek_loy ; copy previous LOY to MSB (4014)
mov tek_lsb,ah
and al,1Fh ; LOY is 5 bits
mov tek_loy,al
cmp lastc,loy ; 2nd LOY in a row?
je tekgh1 ; e = yes, then LSB is valid
mov tek_lsb,0 ; 1st one, clear LSB
tekgh1: mov lastc,loy ; LOY seen, expect HIX (instead of HIY)
tekgh0: clc ; c clear = not completed yet
ret
tekghx: mov ttstate,offset tektxt ; go to TEKTXT next time
mov lastc,0 ; clear last drawing coordinate flag
or status,txtmode ; set text mode in status byte
clc ; carry clear means done
ret
; Extract high-order 5 bits (X or Y, depending on lastc)
tekgh2: and ax,1Fh ; just 5 bits
mov cl,5
shl ax,cl ; shift over 5 bits
cmp lastc,loy ; was last coordinate a low-y?
je tekgh3 ; e = yes, parse hix
mov tek_hiy,ax ; this byte has HIY
mov lastc,hiy
clc
ret
tekgh3: mov tek_hix,ax ; this byte has HIX
mov lastc,hix
clc
ret
tekgh4: and al,1Fh ; just 5 bits
mov tek_lox,al
mov lastc,lox
mov ax,tek_hix ; combine HIX*32
or al,tek_lox ; with LOX
mov bx,tek_hiy ; same for Y
or bl,tek_loy
stc ; set c to say completed operation
ret
TEKXYC endp
TEKRLIN proc near ; RS relative line drawing
cmp al,' ' ; control char?
jae tekrli1 ; ae = no
jmp tektxt ; process control char
tekrli1:cmp al,' ' ; pen up command?
jne tekrli2 ; ne = no, try pen down
mov visible,0 ; do invisible movements
jmp short tekrli3 ; do the command
tekrli2:cmp al,'P' ; pen down command?
jne tekrli4 ; ne = no, return to text mode
mov visible,1 ; set visible moves
tekrli3:mov ax,x_coord ; PC x coordinate of pen
mov bx,y_coord ; y coordinate
call pctotek ; get current pen position in Tek coor
xor cl,cl ; invisible, moveto
call tekdraw ; move that point, set oldx and oldy
mov ttstate,offset tekinc ; next get incremental movement cmds
ret
tekrli4:mov visible,0 ; bad char, reset visibility
mov ttstate,offset tektxt ; assume text
tekrli5:jmp ttstate ; deal with bad char
TEKRLIN endp
; interpret RS inc plot command byte
TEKINC proc near ; get movement character and do cmd
cmp al,' ' ; control char?
jae tekinc1 ; ae = no
jmp tektxt ; process control char
tekinc1:mov bx,oldx
mov cx,oldy
test al,1 ; 'A', 'E', 'I'? Do by bit fields
jz tekinc2 ; z = no
inc bx ; adjust beam position
tekinc2:test al,2 ; 'B', 'F', 'J'?
jz tekinc4
dec bx
tekinc4:test al,4 ; 'D', 'E', 'F'?
jz tekinc8 ; z = no
inc cx
tekinc8:test al,8 ; 'H', 'I', 'J'?
jz tekinc9
dec cx
tekinc9:cmp bx,0 ; too far left?
jge tekinc10 ; ge = no
xor bx,bx ; else stop at the left margin
tekinc10:cmp bx,maxtekx-1 ; too far left?
jle tekinc11 ; le = no
mov bx,maxtekx-1 ; else stop that the left margin
tekinc11:cmp cx,maxteky-1 ; above the top?
jle tekinc12 ; le = not above the top
mov cx,maxteky-1 ; else stop at the top
tekinc12:cmp cx,0 ; below bottom?
jge tekinc13 ; ge = not below bottom
xor cx,cx ; else stop at the bottom
tekinc13:mov ax,bx ; ax is vector x end point
mov oldx,bx
mov bx,cx ; bx is vector y end point
mov oldy,cx
mov cl,visible
jmp tekdraw ; move/draw to that point
tekincb:mov visible,0
jmp tektxt ; reparse the bad char
TEKINC endp
crossini proc near ; set crosshairs for initial screen
mov ax,xmax ; right margin minus 7 dots
add ax,7 ; right most dot
shr ax,1 ; central position
mov bx,ybot ; last scan line
shr bx,1
cmp ax,xcenter ; same as previous call?
jne crossin2 ; ne = no, recenter
cmp bx,ycenter ; same as previous call?
je crossin3 ; e = yes, don't recenter crosshairs
crossin2:mov xcross,ax ; save PC coord for crosshair
mov xcenter,ax ; remember center coord
mov ycross,bx ; this is the center of the screen
mov ycenter,bx ; remember center coord
crossin3: ; Mouse setup
mov mousebuf,0 ; assume no active mouse driver
mov al,mouse ; mouse interrupt 33h
mov ah,35h ; get vector for mouse driver
int dos
mov ax,es
cmp ax,0f000h ; in ROM Bios?
jae crosin1 ; ae = yes
or ax,bx ; check for no vector at all
jz crosin1 ; z = none
cmp byte ptr es:[bx],0cfh ; is this an IRET instruction?
je crosin1 ; e = yes, not our driver
mov ax,msgetbf ; get state buffer size (bytes) to BX
int mouse
add bx,15 ; round up to next paragraph
shr bx,1
shr bx,1
shr bx,1
shr bx,1 ; bytes to paragraphs
mov ah,alloc ; allocate memory
int dos
jc crosin1 ; c = failed
mov mousebuf,ax ; save seg of the mouse status buffer
mov es,ax
xor dx,dx ; buffer address to es:dx
mov ax,msgetst ; get mouse state info
int mouse
jnc crosin2 ; nc = presumed success
call mousefree ; return mouse save buffer
crosin1:ret
crosin2:xor cx,cx ; minimum horizontal/vertical motion
mov dx,xmax ; right most char
add dx,7 ; right most dot (counted from 0)
mov ax,mshoriz ; set min/max horizontal motion
int mouse
mov dx,ybot ; max y (counted from 0)
mov ax,msvert ; set min/max vertical motion
int mouse
ret
crossini endp
; Routine to trigger the crosshairs, wait for a key to be struck, and send
; the typed char (if printable ascii) plus four Tek encoded x,y position
; coordinates and then a carriage return.
; ax, cx, xcross, ycross operate in PC coordinates.
CROSHAIR PROC NEAR
push linepat ; save line drawing pattern
mov linepat,0ffffh ; reset line type to solid
mov ax,xmax ; right margin minus 7 dots
add ax,7
mov temp,ax ; right margin dot
call crosdrawh ; draw initial crosshairs
call crosdrawv
call setmouse ; set mouse there too
crosha1:call tiseof ; is stdin at EOF?
jc crosha2 ; c = yes, exit this mode now
mov dl,0ffh
mov ah,dconio ; read console
int dos
jnz crosha4 ; nz = have char in AL
cmp mousebuf,0 ; is mouse driver active?
je crosha1 ; e = no
mov ax,msread ; mouse, read status and position
int mouse
push bx ; save button press information
cmp cx,xcross ; moved in x direction?
je crosm1 ; e = no
push dx ; save mouse y
call crosdrawv ; erase vertical line
mov xcross,cx ; new position
call crosdrawv ; draw new vertical line
pop dx
crosm1: cmp dx,ycross ; moved in y direction?
je crosm2 ; e = no
call crosdrawh ; erase horizontal line
mov ycross,dx
call crosdrawh ; draw new horizontal line
crosm2: pop bx
test bx,7 ; mouse, was a button pressed?
jz crosha1 ; z = no
mov al,CR ; simulate a CR
crosha4:or al,al ; ascii or scan code returned
jnz arrow5 ; nz = ascii char returned
call tiseof ; is stdin at EOF?
jc crosha2 ; c = yes, exit this mode now
mov ah,coninq ; read scan code
int dos
or al,al ; Control-Break?
jnz crosha3 ; nz = no, something else
crosha2:call crosdrawh ; erase crosshairs
call crosdrawv
pop linepat ; restore line pattern
ret ; exit crosshairs mode
crosha3:cmp al,homscn ; is it 'home'?
jne arrow1 ; ne = no, try other keys
call crosdrawh ; erase crosshairs
call crosdrawv
mov ax,temp ; right margin
shr ax,1 ; central position
mov xcross,ax ; save PC coord for crosshair
mov ax,ybot ; last scan line
shr ax,1
mov ycross,ax ; this is the center of the screen
call crosdrawh ; draw home'd crosshairs
call crosdrawv
call setmouse ; set mouse there too
jmp crosha1
arrow1: cmp al,lftarr ; left arrow?
jne arrow2 ; ne = no
mov cx,-1 ; left shift
jmp short xkeys
arrow2: cmp al,rgtarr ; right arrow?
jne arrow3 ; ne = no
mov cx,1 ; right shift
jmp short xkeys
arrow3: cmp al,uparr ; up arrow?
jne arrow4 ; ne = no
mov cx,-1 ; up shift
jmp short vertkey
arrow4: cmp al,dnarr ; down arrow?
jne badkey ; ne = no, ignore it
mov cx,1 ; down shift
jmp short vertkey
badkey: call tekbeep ; tell user we don't understand
jmp crosha1 ; keep going
; Shifted keys yield ascii keycodes
arrow5: cmp al,'C' and 1fh ; Control-C?
je crosha2 ; e = yes, exit crosshairs mode now
cmp al,shlftarr ; shifted left arrow?
jne arrow6 ; ne = no
mov cx,-10 ; big left shift
jmp short xkeys
arrow6: cmp al,shrgtarr ; shifted right arrow?
jne arrow7 ; ne = no
mov cx,10 ; big right shift
jmp short xkeys
arrow7: cmp al,shuparr ; shifted up arrow?
jne arrow8 ; ne = no
mov cx,-10 ; big up shift
jmp short vertkey
arrow8: cmp al,shdnarr ; shifted down arrow?
jne charkey ; ne = no, send this key as is
mov cx,10 ; big down shift
jmp short vertkey
xkeys: call crosdrawv ; erase vertical line
add cx,xcross ; add increment
jns noxc ; gone too far negative?
xor cx,cx ; s = yes, make it 0
noxc: cmp cx,temp ; too far right?
jb xdraw9 ; b = no
mov cx,temp ; yes, make it the right
xdraw9: mov xcross,cx ; new x value for cross hairs
call crosdrawv ; draw new vertical line
call setmouse ; set mouse there too
jmp crosha1
vertkey:call crosdrawh ; erase horizontal line
add cx,ycross ; adjust cx
jns noyc ; gone negative?
xor cx,cx ; s = yes then make 0
noyc: cmp cx,ybot ; too high?
jb yok ; b = no
mov cx,ybot ; make it maximum
yok: mov ycross,cx ; save new y crosshair
call crosdrawh ; draw new vertical line
call setmouse ; set mouse there too
jmp crosha1
charkey:push ax ; preserve char in al
call crosdrawh ; erase crosshairs
call crosdrawv
pop ax
call outmodem ; send the break character
mov ax,xcross ; set beam to xcross,ycross
mov bx,ycross ; must convert to Tek coordinates
call pctotek ; scale from PC screen coord to Tek
push ax ; save around drawing
push bx
xor cx,cx ; just a move
call tekdraw ; moveto ax,bx in Tek coord
pop bx ; recover Tek y
pop ax ; recover Tek x
call sendpos ; send position report to host
pop linepat ; recover current line drawing pattern
mov ttstate,offset tektxt ; go to TEKTXT next time
mov lastc,0 ; clear last drawing coordinate flag
or status,txtmode ; set text mode in status byte
ret
CROSHAIR ENDP
; draw vertical crosshair line at x = xcross, xor with picture
crosdrawv proc near
mov al,ccode ; save current pixel op
push ax
push cx
mov si,xcross ; move to x= xcross
mov ax,si ; ending x coord
xor di,di ; starting y coord
mov bx,ybot ; bottom y coord
mov cl,pixxor ; xor pixels
call line ; draw vertical
pop cx
pop ax ; recover current pixel op
mov ccode,al ; restore it
ret
crosdrawv endp
; draw horizontal crosshair line at y = ycross, xor with picture
crosdrawh proc near
mov al,ccode ; save current pixel op
push ax
push cx
mov di,ycross ; set y = ycross
mov bx,di ; ending y
xor si,si ; starting x
mov ax,temp ; max x value
mov cl,pixxor ; set XOR code
call line ; draw to (xcross+12, ycross)
pop cx
pop ax ; recover current pixel op
mov ccode,al ; restore it
ret
crosdrawh endp
; Set mouse cursor position to xcross,ycross. Ignored if no active mouse.
setmouse proc near
cmp mousebuf,0 ; is mouse driver is active?
je setmou1 ; e = no
mov cx,xcross
mov dx,ycross
mov ax,mswrite ; set mouse position
int mouse
setmou1:ret
setmouse endp
; Return DOS memory allocated as mouse status buffer
mousefree proc near
push es
mov ax,mousebuf ; seg of mouse save buffer
mov es,ax ; allocated segment
mov ah,freemem ; free it
int dos
mov mousebuf,0 ; clear mouse presence too
pop es
ret
mousefree endp
; Return mouse state and free state save buffer
mousexit proc near
mov ax,mousebuf ; segment of state save buffer
or ax,ax ; is mouse driver active?
jz mousex1 ; z = no
push es
mov es,ax
xor dx,dx ; address is in es:dx
mov ax,mssetst ; set mouse driver state from buffer
int mouse
pop es
call mousefree ; return memory to DOS
mousex1:ret
mousexit endp
; SENDPOS sends position of cross-hairs to the host.
; ax has Tek X and bx has Tek Y coord of center of crosshair
SENDPOS PROC NEAR
push bx ; preserve register
call sendxy ; send x coord
pop ax
call sendxy ; send y coord
mov al,cr ; follow up with cr
call outmodem
ret
SENDPOS ENDP
; Write binary number in AX as decimal asciiz to buffer pointer DI.
dec2di proc near ; output number in ax using base in cx
; corrupts ax, cx, and dx
mov cx,10
dec2di1:xor dx,dx ; clear high word of numerator
div cx ; (ax / cx), remainder = dx, quotient = ax
push dx ; save remainder for outputting later
or ax,ax ; any quotient left?
jz dec2di2 ; z = no
call dec2di1 ; yes, recurse
dec2di2:pop dx ; get remainder
add dl,'0' ; make digit printable
mov [di],dl ; store char in buffer
inc di
mov byte ptr[di],0 ; add terminator
ret
dec2di endp
; SENDXY sends value of ax as Tek encoded bytes
; ax is in Tek coordinates
SENDXY PROC NEAR
shl ax,1
shl ax,1 ; move all but lower 5 bits to ah
shl ax,1
shr al,1
shr al,1 ; move low five bits to low 5 bits
shr al,1
or ah,20h ; make it a printing char as per TEK
xchg al,ah ; send high 5 bits first
call outmodem
xchg al,ah ; then low five bits
or al,20h
call outmodem
xchg ah,al ; al is first sent byte
ret
SENDXY ENDP
SENDID PROC NEAR ; pretend VT340
mov bx,offset tekid ; VT320 identification string
sndid1: mov al,[bx] ; get char from sequence
or al,al ; end of sequence?
jz sndid0 ; z = yes, return
call outmodem ; send it out the port
inc bx
jmp sndid1
sndid0: ret
SENDID ENDP
; SENDSTAT - send status and cursor position to host
SENDSTAT PROC NEAR
mov al,STATUS ; get tek status
or al,20h ; make it printable
call OUTMODEM ; and send it
mov ax,oldx ; now send x coordinate (oldx is Tek)
call SENDXY
mov ax,oldy ; and y coordinate (oldy is Tek coord)
call SENDXY
mov al,cr ; end with a cr
call OUTMODEM
ret
SENDSTAT ENDP
; Convert X and Y from PC coordinates to Tek coordinates. AX = X, BX = Y
; for both input and output.
pctotek proc near
mul xdiv ; scale from PC screen coord to Tek
div xmult
xchg bx,ax ; save Tek x coord in bx
neg ax ; y axis. Turn upside down for Tek
add ax,ybot
mul ydiv ; scale y from PC screen coord to Tek
div ymult
xchg ax,bx ; ax has X, bx has Y in Tek coords
ret
pctotek endp
; Routine to output character in AL to the screen.
OUTSCRN PROC NEAR ; put one character to the screen
cmp rxtable+256,0 ; translation turned off?
je outscr2 ; e = yes, no translation
push bx
mov bx,offset rxtable ; address of translate table
xlatb ; new char is in al
and al,7fh ; retain only lower seven bits
pop bx
outscr2:
mov ah,ccode ; assume transparent chars
push ax ; save ccode
mov ccode,pixfor ; write in foreground
cmp chcontrol,0 ; transparent char writing?
je outscr3 ; e = yes
or ccode,pixbak ; write background dots too
outscr3:cmp al,lf ; this moves down the screen
je outscr4 ; e = yes, a lf
cmp al,' ' ; printable?
jb outscr5 ; b = no
outscr4:call testfull ; check for full screen
outscr5:call remcursor ; remove text cursor symbol
call putc ; routine to draw characters
call setcursor ; draw text cursor symbol
pop ax ; recover ccode
mov ccode,ah
ret
OUTSCRN ENDP
; Test if screen is full. If full sound beep, wait for any keyboard input
; (skip kbd reading if stdin is redirected).
testfull proc near
push ax
mov ax,x_coord
cmp ax,xmax ; at end of the line?
jbe testfu1 ; be = no
mov x_coord,0 ; wrap to next line
add y_coord,8 ; next row
testfu1:mov ax,ybot ; get last scan line
inc ax ; number of scan lines
cmp ax,y_coord ; minus where char bottom needs to go
jae testfu3 ; ae = enough space for char
call tekbeep ; tell the user we are waiting
call tiseof ; EOF on redirected stdin?
jc testfu2 ; c = yes, proceed anyway
mov ah,coninq ; read keyboad via DOS
int dos ; wait for keystroke
or al,al ; scan code being returned?
jne testfu2 ; ne = no
mov ah,coninq ; clear away scan code too
int dos
testfu2:call tekcls ; clear the screen
mov x_coord,0
mov y_coord,0
testfu3:pop ax ; recover current character
ret
testfull endp
; Draw text cursor symbol by xor-ing. Sets xcursor,ycursor to symbol position.
setcursor proc near
cmp tekcursor,0 ; suppress cursor?
je setcurs0 ; e = yes
cmp cursorst,0 ; is cursor off now?
jne setcurs0 ; ne = no
cmp putc,offset mputc ; pure mono character display routine?
jne setcurs1 ; ne = no
setcurs0:ret ; no cursor for pure mono
setcurs1:mov bh,ccode ; current drawing code, save it
mov bl,chcontrol ; and transparent writing state
push bx ; save ccode
push ax
mov ccode,pixxor ; xor with foreground coloring
mov chcontrol,0 ; transparent characters
push x_coord ; save current operating point (PC)
push y_coord
mov ax,x_coord ; where cursor symbol starts, X axis
cmp ax,xmax ; beyond last character position?
jbe setcurs2 ; be = no
mov ax,xmax ; yes, stop at last, for wrapping
setcurs2:mov xcursor,ax ; remember where we drew symbol
mov x_coord,ax ; set this for drawing the symbol
mov ax,y_coord
mov ycursor,ax
mov al,7fh ; symbol code to draw
call putc ; routine to draw characters
pop y_coord
pop x_coord
pop ax
pop bx ; recover ccode
mov ccode,bh
mov chcontrol,bl
mov cursorst,1 ; say cursor is on
ret
setcursor endp
; Remove text cursor symbol by xor-ing with itself. Xcursor, ycursor is the
; PC coord of the cursor symbol.
remcursor proc near
cmp tekcursor,0 ; suppress cursor?
je remcurs0 ; e = yes
cmp cursorst,0 ; is cursor off now?
je remcurs0 ; e = yes
cmp putc,offset mputc ; pure mono character display routine?
jne remcurs1 ; ne = no
remcurs0:ret ; no cursor for pure mono
remcurs1:mov bh,ccode ; current drawing code, save it
mov bl,chcontrol ; and transparent writing state
push bx ; save ccode
push ax
mov ccode,pixxor ; xor with foreground coloring
mov chcontrol,0 ; transparent characters
push x_coord ; save current operating point (PC)
push y_coord
mov ax,xcursor ; where last cursor was written
mov x_coord,ax ; setup for xor writing to remove it
mov ax,ycursor
mov y_coord,ax
mov al,7fh ; cursor symbol
call putc ; routine to draw characters
pop y_coord
pop x_coord
pop ax
pop bx ; recover ccode
mov ccode,bh
mov chcontrol,bl
mov cursorst,0 ; say cursor is off
ret
remcursor endp
; TEKCLS routine to clear the screen.
; Entry point tekcls1 clears screen without resetting current point.
TEKCLS PROC NEAR
cmp flags.vtflg,tttek ; regular Tek terminal?
je tekcls0 ; e = yes
test tekflg,1 ; Tek mode active yet?
jnz tekcls0 ; nz = yes
ret ; else ignore this call
tekcls0:mov x_coord,0 ; starting text coordinates
mov y_coord,0
mov oldx,0 ; assumed cursor starting location
mov oldy,maxteky ; top right corner (Tek coord)
mov scalex,0 ; clear last plotted point (PC coord)
mov scaley,0
mov lastc,0 ; last parsed x,y coordinate
mov visible,0 ; make lines invisible
mov bypass,0 ; clear bypass condition
mov ttstate,offset tektxt ; do displayable text
mov prestate,offset tektxt
tekcls1:push ax ; save registers
push cx
mov bl,ccode ; save pixel op code
push bx
cmp graph_mode,hercules ; Hercules?
jne tekclsw ; ne = no
call hgraf ; set Hercules board to Graphics mode
jmp tekcls7
tekclsw:cmp graph_mode,wyse700 ; Wyse 700?
jne tekcls2 ; ne = no
call wygraf ; set board to Graphics mode & cls
jmp tekcls7
tekcls2:xor di,di ; point to start of screen, di=row
mov ccode,pixbak ; write in background
call psetup ; setup graphics routine and es:di
mov cx,4000h ; CGA, 200 lines times 80 bytes worth
cmp graph_mode,cga ; cga?
je tekcls3 ; e = yes
mov cx,8000h ; Olivetti, 400 lines times 80 bytes
cmp graph_mode,olivetti ; AT&T-Olivetti?
je tekcls3 ; e = yes
cmp graph_mode,toshiba ; Toshiba?
je tekcls3 ; e = yes
cmp graph_mode,vaxmate ; VAXmate?
jne tekcls4 ; ne = no
tekcls3:cld ; clear screen directly of text stuff
xor ax,ax
test gbcol,7 ; background is dark?
jz tekcls3a ; z = yes
mov ax,0ffffh ; light, set all pixels
tekcls3a:shr cx,1 ; do words
rep stosw ; clear the words
jmp short tekcls7
tekcls4:cmp graph_mode,ega ; EGA?
je tekcls5 ; e = yes
cmp graph_mode,monoega ; EGA with mono display?
je tekcls5 ; e = yes
cmp graph_mode,colorega ; EGA with medium resolution monitor?
je tekcls5 ; e = yes
jmp short tekcls6 ; else use Bios
tekcls5: ; EGA clear screen quickly
mov ax,0ff08h ; set all 8 bits to be changed
call ega_gc ; set bit mask register accordingly
mov ax,0003h ; data rotate reg, write unmodified
call ega_gc ;
mov cx,ybot ; last scan line
inc cx ; number of scan lines
mov ax,80/2 ; words (2*bytes) per scan line
mul cx
mov cx,ax ; cx = number of bytes to clear
call fixcolor ; fix colors first, if req'd
mov al,gbcol ; select background colour
mov ah,al ; copy for word stores
cld
rep stosw ; write backgound color
jmp short tekcls7
tekcls6:push es ; clear screen by scrolling up
call tcmblnk ; clear screen, for Environments
pop es
tekcls7:xor si,si ; starting x (in case screen is
xor di,di ; starting y cleared by user)
pop bx
mov ccode,bl ; restore pixel op code
mov xcursor,0 ; position of text cursor symbol
mov ycursor,0
mov cursorst,0 ; say text cursor is off (new screen)
call setcursor ; draw text cursor symbol
pop cx
pop ax
ret
TEKCLS ENDP
; Routine to draw a line on the screen, using TEKTRONIX coordinates.
; X coordinate in AX, 0=left edge of screen, 1023=right edge of screen.
; Y coordinate in BX, 0=bottom of screen, 779=top of screen.
; CL=0 - invisible move, else draw in foreground colors
TEKDRAW PROC NEAR
mov si,scalex ; get old x already scaled
mov di,scaley ; get old y already scaled
call scale ; scale new end point to PC coords
or cl,cl ; invisible drawing?
jz moveto ; z = just move, skip draw part
mov cl,pixfor ; draw in foreground color
call LINE ; draw the line
moveto: mov x_coord,ax ; update text coordinates to match
mov y_coord,bx ; last drawn point
ret
TEKDRAW ENDP
; Scale TEKTRONIX coordinates to the currently defined screen coordinates
; AX holds X axis, BX holds Y axis. Both are changed from Tektronix coord
; to PC coordinates by this procedure.
SCALE PROC NEAR
push dx
push si
cmp ax,1023 ; limit x axis
jbe scale1 ; be = not out of bounds
mov ax,1023
scale1: cmp bx,779 ; limit y axix
jbe scale2 ; be = not out of bounds
mov bx,779
scale2: mov oldx,ax ; save current Tek x for next draw
mov oldy,bx ; save current Tek y for next draw
mul xmult ; scale x-coord
mov si,xdiv ; get the divisor
shr si,1 ; halve it
add ax,si ; add in - to round to nearest integer
adc dx,0
div xdiv
push ax
mov ax,bx
mul ymult ; scale y-coord
mov si,ydiv ; get divisor
shr si,1 ; halve it
add ax,si ; add in - to round to nearest integer
adc dx,0
div ydiv
mov bx,ybot
sub bx,ax ; put new Y in right reg
jns scale3 ; ns = not too far
xor bx,bx
scale3: pop ax ; put new X in right reg
mov scalex,ax ; save scaled values
mov scaley,bx
pop si
pop dx
ret
SCALE ENDP
; LINE Subroutine to plot a line with endpoints in AX,BX and SI,DI.
; fast line drawing routine for the IBM PC
;
; Registers at CALL
; -----------------
; SI=Start X coord, all in PC coordinates
; DI=Start Y coord
; AX=End X coord
; BX=End Y coord
; CCODE=pixel operation code
; BP= line drawing pattern (is changed here by rotation)
; registers are all unchanged
LINE PROC NEAR
push ax
push bx
push cx
push dx
push si
push di
push es
mov bp,linepat ; store active line pattern word in BP
mov dl,ccode ; existing pixel op code
push dx ; save around line drawing
mov ccode,cl ; save color code in ccode for use by plot()
; first get coord to achieve increasing x; deltax >= 0
sub ax,si ; deltax = x2 - x1
jge line1 ; ge = going to the right, as desired
neg ax ; make deltax non-negative
sub si,ax ; swap the x coordinates
xchg bx,di ; swap the y coordinates too
; second, compute deltay. ax = deltax, si = x1
line1: sub bx,di ; deltay = y2 - y1
call psetup ; setup display adapter for plotting
; and setup es:di to screen memory
; Choose algorithm based on |deltay| < |deltax| (use shallow) else steep.
; We arrange matters such that both deltas are non-negative.
cmp bx,0 ; deltay
jge line2 ; ge = non-negative
neg linelen
neg bx ; make non-negative
line2: cmp bx,ax ; |deltay| versus |deltax|
jbe shallow ; be = do shallow algorithm
jmp steep ; else do steep algorithm
; shallow algorithm, move along x, di=y1, bx=deltay, si=x1, ax=deltax
shallow:add bx,bx ; bx = 2*deltay
mov cx,ax ; cx = number of steps (deltax here)
inc cx ; loop dec's cx before testing
mov dx,bx ; dx holds error
sub dx,ax ; error = 2*deltay - deltax
add ax,ax ; ax = 2*|deltax|
shal1: call plotptr ; Plot(x,y)
cmp dx,0
jle shal2 ; le = error <= 0
call pincy ; increment y by one scan line
sub dx,ax ; error = error - 2*deltax
shal2: add dx,bx ; error = error + 2*deltay
inc si ; x = next dot right
loop shal1
jmp short plotex
; steep algorithm, move along y, di=y1, bx=deltay, si=x1, ax=deltax
steep: add ax,ax ; ax = 2*deltax
mov dx,ax ; dx holds error
sub dx,bx ; error = 2*deltax(bx) - deltay (bx)
mov cx,bx ; cx = number of steps (deltay here)
inc cx ; loop dec's cx before testing
add bx,bx ; bx = 2*|deltay|
stee1: call plotptr ; Plot(x,y) x = ax, y = di
cmp dx,0
jle stee2 ; le error <= 0
inc si ; x = next dot right
sub dx,bx ; error = error - 2*deltay
stee2: add dx,ax ; error = error + 2*deltax
call pincy ; increment y
loop stee1
;;; jmp plotex
plotex: pop dx ; al has orginal pixel op
mov ccode,dl ; restore it
pop es
pop di
pop si
pop dx ; restore the world
pop cx
pop bx
pop ax
ret
LINE ENDP
; Draw a rectangle.
; lower left corner: x = param[0], y = param[2], Tek coordinates
; distance: dx = param[4], dy = param[6], Tek coordinates, all positive
rectdraw proc near
push x_coord
push y_coord
mov ax,param[0] ; lower left corner is start, x part
mov bx,param[2] ; y part
push ax ; x0
push bx ; y0
xor cl,cl ; moveto
call tekdraw
pop bx
pop ax
add bx,param[6] ; y0 + dy
mov cl,1 ; draw x0,y0 to x0,y0+dy
push ax
push bx
call tekdraw
pop bx
pop ax
add ax,param[4] ; x0+dx
mov cl,1 ; draw x0,y0+dy to x0+dx,y0+dy
push ax
call tekdraw
pop ax
mov bx,param[2] ; y0
push bx
mov cl,1
call tekdraw
pop bx
mov ax,param[0] ; x0
mov cl,1
call tekdraw ; complete the box
pop y_coord
pop x_coord
ret
rectdraw endp
; Fill a rectangle with a given pattern.
; lower left corner: x = param[0], y = param[2], Tek coordinates
; distance: dx = param[4], dy = param[6], Tek coordinates, all positive
; fill pattern = param[8]
rectfil proc near
push oldx
push oldy ; save regular point/line old coords
mov ax,param ; get Tek X coord of lower left corner
mov bx,param[2] ; get Tek Y coord
call scale ; convert to PC in ax,bx, scalex/y
mov rectx1,ax ; lower left corner in PC coords
mov recty1,bx
mov ax,param ; convert ending points, start Tek X
add ax,param[4] ; Tek X + DX
mov bx,param[2] ; start Tek Y
add bx,param[6] ; Tek Y + DY
call scale
pop oldy
pop oldx
mov rectx2,ax ; upper right corner PC X coord
mov recty2,bx ; upper right corner PC Y coord
mov si,rectx1 ; starting x PC coord to si
mov di,recty2 ; starting y PC coord to di
mov cx,recty1 ; plotting from top down on screen
sub cx,bx ; cx = # scan lines - 1
mov numlines,cx ; remember here
mov bx,param[8] ; fill pattern number
or bx,bx ; zero?
jz rectfi1 ; z = yes, use current pointer
cmp bx,numfil ; pattern number is too large?
ja rectfi1 ; a = yes, use current pointer
dec bx ; count internally from 0
shl bx,1 ; make this a word pointer
mov bx,fillist[bx] ; get pointer to pattern
mov fillptr,bx ; remember it here
rectfi1:mov cx,rectx2 ; ending x coord
sub cx,rectx1 ; number of horizontal pixels - 1
inc cx ; number of horizontal pixels
call psetup ; set up dsp and di to screen offset
; di points to whole byte, do bits in byte in gfplot
rectfi2:push bx
mov bx,recty1 ; lower screen y (larger value)
sub bx,numlines ; alignment: global screen sync
and bx,7 ; modulo 8
add bx,fillptr ; offset of fill pattern start
mov bl,[bx] ; pattern byte
mov fill,bl ; save here for gfplot
pop bx
call gfplot ; line fill routine
call pincy ; next line
dec numlines
jns rectfi2 ; ns = more to do
ret
rectfil endp
;;;;;;; EGA plot support routines
psetupe proc near ; EGA setup for plotting
push ax
mov linelen,80 ; for y going down screen by pincy
mov ax,segscn ; set es to screen memory segment
mov es,ax
mov ax,0205h ; mode: write mode 2
call ega_gc
mov ax,0003h ; assume writing bits directly
test ccode,pixfor+pixbak ; direct foreground/background write?
jnz psete2 ; nz = yes
mov ax,1003h ; assume OR
test ccode,pixor ; OR?
jnz psete2 ; nz = yes
mov ax,1803h ; assume XOR
test ccode,pixxor ; inverting bits?
jnz psete2 ; nz = yes
mov ax,0803h ; then use AND
psete2: call ega_gc ; set controller
mov ax,80 ; compute starting point in regen buff
mul di
mov di,ax ; di = di * 80
pop ax
ret
psetupe endp
pincye proc near ; EGA inc y
add di,linelen ; includes sign of deltay
ret
pincye endp
pltega proc near ; EGA plot(x,y). x is in si, y is in di
ror bp,1 ; rotate line pattern
jc pltega1 ; c = a 1 bit to be plotted
cmp ccode,pixfor+pixbak ; plot both 1's and 0's?
je pltega1 ; e = yes
ret ; else ignore the 0 bit
pltega1:push bx
push si
push di
mov bx,si ; want si/8 for bytes along line
shr si,1
shr si,1
shr si,1
add di,si ; starting point in regen buffer
and bx,0007h ; leave lower 3 bits for bit in byte
mov bh,masktab[bx] ; 0-7 into bit mask in byte, x pos
mov bl,ccode ; get line type code
call ega_plt
pop di
pop si
pop bx
ret
pltega endp
; Plot bit pattern in "fill" as 8 horizontal pixels, starting at x,y (si,di)
; and continuing across the line for cx pixels. psetupe has been called.
bpltega proc near ; EGA plot(x,y). x is in si, y is in di
push bx
push cx
push si
push di
mov bx,si ; want si/8 for bytes along line
shr si,1
shr si,1
shr si,1
add di,si ; starting byte in regen buffer
; di = offset in regen buffer
and bl,7 ; get bit in byte (di = byte aligned)
jz bplteg1 ; z = aligned already
xchg bl,cl ; get shift to cl, low count to bl
mov bh,fill ; 8-bit fill pattern
mov al,bh ; get complement of pattern too
not al
shl bh,cl ; trim cl bits from the left
shr bh,cl
shl al,cl ; trim them from the right edge
shr al,cl ; restore pattern
xchg cl,bl ; put count back in cx
add cl,bl ; add bits taken care of
adc ch,0
jmp short bplteg2 ; do this partial byte now
bplteg1:mov bh,fill ; fill pattern
mov al,bh ; make inverted pattern
not al
cmp cx,8 ; do all 8 bits?
jae bplteg2 ; ae = yes
push cx ; final byte fixup
sub cl,8 ; cl = - (number of bits to omit)
neg cl ; cl = number of bits to omit
mov al,bh ; get complement of pattern too
not al
shr bh,cl ; trim them from the right edge
shl bh,cl ; restore pattern
shr al,cl ; trim them from the right edge
shl al,cl ; restore pattern
pop cx
bplteg2:push ax
cmp ccode,pixfor+pixbak ; do both fore and background?
jne bplteg2a ; ne = no
push bx
mov bh,al ; get complemented pattern
mov bl,pixbak ; write background
call ega_plt
pop bx
bplteg2a:mov bl,ccode ; get line type code
call ega_plt
bplteg3:pop ax
inc di ; next byte right
sub cx,8 ; did these
cmp cx,0 ; anything left to do?
jg bplteg1 ; a = yes, repeat
pop di
pop si
pop cx
pop bx
ret
bpltega endp
;;;;;;;; CGA plot support routines
; The CGA graphics memory mapping in mode 6 (640 by 200) is 8 dots per byte,
; left most dot in the high bit, 80 bytes per scan line, scan line segments
; alternating between 0b800h (even lines 0, 2, ...) and 0ba00h (odd lines).
psetupc proc near ; CGA setup for plotting
push ax
push cx
mov linelen,80 ; 80 bytes per scan line
mov cx,segscn
mov es,cx
mov cx,di ; save copy of di, start y line
; compute starting point in regen buff
shr di,1 ; half the lines in each bank
mov ax,80 ; 80 bytes per line
mul di
mov di,ax ; di = di * 80 / 2
test cx,1 ; even or odd line
jz psetc1 ; z = even
add di,2000h ; offset to odd bank (seg 0ba00h)
psetc1: and di,3fffh
pop cx
pop ax
ret
psetupc endp
pincyc proc near ; CGA inc y
cmp linelen,0 ; increasing or decreasing y?
jl pinyc2 ; l = decreasing
cmp di,2000h ; in upper bank now?
jb pinyc1 ; b = no, in lower bank
add di,linelen ; add a line
pinyc1: add di,2000h ; switch banks
and di,3fffh ; roll over address
ret
pinyc2: cmp di,2000h ; in upper bank now?
jae pinyc4 ; ae = yes
add di,linelen ; subtract a line
pinyc4: add di,2000h ; switch banks
and di,3fffh ; roll over address
ret
pincyc endp
pltcga proc near ; CGA plot(x,y). x is in si, y is in di
push bx ; used for HGA and Wyse plots also.
push si
push di
ror bp,1 ; rotate line pattern
jc pltcg6 ; c = 1 bit to be plotted
cmp ccode,pixfor+pixbak ; plot both 1's and 0's?
jne pltcg3 ; ne = no
pltcg6: mov bx,si ; want si/8 for bytes along line
shr si,1
shr si,1
shr si,1
add di,si ; starting point in regen buffer
and bx,0007h ; leave lower 3 bits for bit in byte
; di = offset in regen buffer
mov bh,masktab[bx] ; 0-7 into bit mask in byte. x position
mov bl,ccode ; get line type code
test bl,pixfor+pixor ; draw in foreground color or OR?
jz pltcg1 ; z = no
test bl,pixor ; OR?
jnz pltcg5 ; nz = yes
test gfcol,7 ; is foreground dark?
jz pltcg4 ; z = yes, punch a hole
pltcg5: or es:[di],bh ; drawn
jmp short pltcg3
pltcg1: test bl,pixbak ; draw in background (erase)?
jz pltcg2 ; z = no
test gbcol,7 ; is background light?
jnz pltcg5 ; nz = yes
pltcg4: not bh ; invert the bit
and es:[di],bh ; erase the dot
jmp short pltcg3
pltcg2: xor es:[di],bh ; xor in this color
pltcg3: pop di
pop si
pop bx
ret
pltcga endp
; Plot bit pattern in fill as 8 horizontal pixels, starting at x,y (si,di)
; and continuing across the line for cx pixels. psetupc has been called.
bpltcga proc near ; CGA plot(x,y). x is in si, y is in di
push bx ; used for HGA and Wyse plots also.
push cx
push si
push di
mov bx,si ; want si/8 for bytes along line
shr si,1
shr si,1
shr si,1
add di,si ; starting byte in regen buffer
; di = offset in regen buffer
and bl,7 ; get bit in byte (di = byte aligned)
jz bpltcg5 ; z = aligned already
xchg bl,cl ; get shift to cl, low count to bl
mov bh,fill ; 8-bit fill pattern
shl bh,cl ; trim cl bits from the left
shr bh,cl
push cx
mov al,0ffh ; 1's are original bits to be saved
sub cl,8 ; max field width is 8 bits
neg cl ; 8-number of bits trimmed from left
shl al,cl ; al now holds save-field bit pattern
pop cx
xchg cl,bl ; put count back in cx
add cl,bl ; add bits taken care of
adc ch,0
jmp short bpltcg4 ; do this partial byte now
bpltcg5:mov bh,fill ; fill pattern
xor al,al ; assume saving no bits
cmp cx,8 ; do all 8 bits?
jae bpltcg4 ; ae = yes
push cx ; final byte fixup
mov al,0ffh ; 1's are original bits to be saved
shl al,cl
shr al,cl ; al now holds save-field bit pattern
sub cl,8 ; cl = - (number of bits to omit)
neg cl ; cl = number of bits to omit
shr bh,cl ; trim them from the right edge
shl bh,cl ; restore pattern
pop cx
bpltcg4:mov bl,ccode ; get line type code
cmp bl,pixfor+pixbak ; set both fore and background?
jne bpltcg9 ; ne = no
test gfcol,7 ; is foreground dark?
jnz bpltcg8 ; nz = no
not bh ; invert the bit pattern
or bh,al ; set bits to be saved
sub bh,al ; trim off saved bits from this field
bpltcg8:mov ah,es:[di] ; get contents of memory cell
and ah,al ; preserve bit field given by al
or bh,ah ; mask in saved bits
mov es:[di],bh ; write the byte
jmp short bpltcg3 ; done
bpltcg9:test bl,pixfor+pixor ; draw in foreground?
jz bpltcg1 ; z = no
test bl,pixor ; OR?
jnz bpltcg7 ; nz = yes
test gfcol,7 ; is foreground dark?
jz bpltcg6 ; z = yes, punch a hole
bpltcg7:or es:[di],bh ; drawn
jmp short bpltcg3
bpltcg1:test bl,pixbak ; draw as background (erase)?
jz bpltcg2 ; z= do not draw as background (erase)
test gbcol,7 ; is background light?
jz bpltcg6 ; z = no
or es:[di],bh ; drawn
jmp short bpltcg3
bpltcg6:not bh
and es:[di],bh ; erase the dots
jmp short bpltcg3
bpltcg2:xor es:[di],bh ; xor in this color
bpltcg3:inc di ; next byte right
sub cx,8 ; did these
cmp cx,0 ; anything left to do?
jg bpltcg5 ; a = yes, repeat
pop di
pop si
pop cx
pop bx
ret
bpltcga endp
;;;;;;; Wyse-700 plot support routines
; The Wyse graphics memory map in mode 0D3h (1280 by 800) is 8 dots per byte,
; left most dot in the high bit, 160 bytes per scan line, scan line segments
; sequence as 0a000h even lines, and same for odd lines
psetupw proc near ; Wyse setup for plotting
push ax
push cx
push dx
mov linelen,160 ; for y going down screen by incy
mov ax,segscn ; base segment of display memory
mov es,ax
mov cx,di ; save copy of di, start y line
; compute starting point in regen buff
shr di,1 ; half the lines in each bank
mov ax,160
mul di
mov di,ax ; di = di * 160 / 2
mov dx,wymode
shr cx,1 ; compute bank from 1 lsb of line num
jnc psetw2 ; nc = it is in bank 0 (0b000h)
mov ax,wybodd ; select odd bank
out dx,al
jmp short psetw3
psetw2: mov ax,wybeven ; select even bank
out dx,al
psetw3: mov bnkchan, al ; bank has changed
pop dx
pop cx
pop ax
ret
psetupw endp
;
; Wyse-700 has two banks. Line 0, 2, 4 ... are in bank 0, and 1, 3, 5 ... are
; in bank 1. Lines 0 and 1 have same addresses, lines 2 and 3 have same
; addresses etc. We have to change bank every time Y changes but we
; have to count new address only after two Y-value changes. Variable
; bnkchan is a flag for us to know into which bank to write.
;
pincyw proc near ; Wyse inc y, step offset of line
push ax
push dx
mov dx,wymode ; Wyse conrol register
mov al,wybeven ;
cmp bnkchan,wybeven ; was last write into even bank ?
jne pincywe ; ne = no
mov al,wybodd ; yes, set ready for odd bank
out dx,al ;
mov bnkchan,al ; set to odd
jmp short pincywo
pincywe:mov al,wybeven ; set ready foe even bank
out dx,al ; select it
mov bnkchan,al ; set to odd
pincywo:cmp linelen,0 ; increasing y?
jg pinyw2 ; g = yes
cmp al,wybeven ; from high (1) to low (0) bank ?
je pinyw4 ; e = yes
add di,linelen ; no, add a line
jmp short pinyw4
pinyw2: cmp al,wybodd ; from low (0) to high (1) bank ?
je pinyw4 ; e = yes
add di,linelen ; no, add a line
pinyw4: and di,0ffffh ; roll over address
pop dx
pop ax
ret
pincyw endp
;;;;;;; HGA plot support routines
; The HGA graphics memory mapping in mode 255 (720 by 348) is 8 dots per byte,
; left most dot in the high bit, 90 bytes per scan line, scan line segments
; sequence as 0b000h, 0b200h, 0b400h, 0b800h for lines 0-3 and repeat 90 bytes
; higher for the rest.
psetuph proc near ; HGA setup for plotting
push ax
push cx
mov linelen,90 ; for y going down screen by incy
mov ax,segscn ; base segment of display memory
mov es,ax
mov cx,di ; save copy of di, start y line
; compute starting point in regen buff
shr di,1 ; quarter the lines in each bank
shr di,1
mov ax,90
mul di
mov di,ax ; di = di * 90 / 4
and cx,3 ; compute bank from 2 lsb of line num
jcxz pseth2 ; z means it is in bank 0 (0b000h)
pseth1: add di,2000h ; add offset for each bank
loop pseth1 ; do cx times
pseth2: pop cx
pop ax
ret
psetuph endp
pincyh proc near ; HGA inc y, step offset of line
cmp linelen,0 ; increasing y?
jg pinyh2 ; g = yes
cmp di,2000h ; in lowest for four banks?
ja pinyh1 ; a = no
add di,linelen ; yes, add a line
pinyh1: add di,6000h ; move back by adding a lot
and di,7fffh ; roll over address
ret
pinyh2: cmp di,6000h ; in top most bank?
jb pinyh4 ; b = no
add di,linelen ; yes, first add a line
pinyh4: add di,2000h ; switch to next bank
and di,7fffh ; roll over address
ret
pincyh endp
;;;;;;; AT&T-Olivetti, Toshiba, VAXmate Graphics Adapter plot support routines
; The graphics memory mapping in 640 by 400 mode is 8 dots per byte,
; left most dot in the high bit, 80 bytes per scan line, scan line segments
; sequence as 0b800h, 0ba00h, 0bc00h, 0be00h for lines 0-3 and repeat 80 bytes
; higher for the rest. Use Hercules line incrementing (inc y) and CGA dot
; writing. This is a monographic display.
psetupo proc near ; setup for plotting
push ax
push cx
mov linelen,80 ; for y going down screen by incy
mov ax,segscn ; base segment of display memory
mov es,ax
mov cx,di ; save copy of di, start y line
; compute starting point in regen buff
shr di,1 ; quarter the lines in each bank
shr di,1
mov ax,80
mul di
mov di,ax ; di = di * 80 / 4
and cx,3 ; compute bank from 2 lsb of line num
jcxz pseto2 ; z means it is in bank 0 (0b800h)
pseto1: add di,2000h ; add offset for each bank
loop pseto1 ; do cx times
pseto2: pop cx
pop ax
ret
psetupo endp
;;;;;;;; Monochrome, simulate dots with text char
psetupm proc near
mov linelen,1 ; 80 characters but one line
ret
psetupm endp
pltmon proc near ; Monochrome dot plot
mov x_coord,si ; put dot at row=di, col=si, PC Coord
mov y_coord,di
push ax
mov al,'+' ; our dot character
call mputc ; display text char
pop ax
ret
pltmon endp
; Plot bit pattern in fill as 8 horizontal pixels, starting at x,y (si,di)
; and continuing across the line for cx pixels. Destroys CX.
bpltmon proc near ; Mono plot(x,y). x is in si, y is in di
jmp pltmon ; a dummy for the present
bpltmon endp
pincym proc near ; Monochrome inc y
add di,linelen ; includes sign
ret
pincym endp
; GPUTC - a routine to send text characters from font to true graphics boards
; such as EGA, Hercules or CGA. Char is in al. Drawing routine ptr is gcplot.
gputc proc near
cmp al,' ' ; control character or space?
ja gputc2 ; a = no, display the char
je gputc1 ; e = space char
jmp putctrl ; else handle controls at putctrl
gputc1: cmp spcontrol,0 ; non-destructive space?
jne gputc2 ; ne = no, do actual writing
cmp chcontrol,0 ; write transparently?
jne gputc2 ; ne = no, opaque, draw the char
call testfull ; check on full screen
jmp incx ; move to next char position
gputc2: push bx ; first save some registers
push cx
push es
push di
mov bl,al ; now BL has char to be displayed
and bl,7fh ; no high bits allowed here
; set board mode
mov di,y_coord ; get current y coord (char bottom)
sub di,7 ; start 7 lines higher
jnc gputc3 ; nc = ok
xor di,di ; move up to first line
mov y_coord,7 ; and reset scan line indicator
gputc3: call psetup ; enter with di=line number, sets es:di to start of
; line in regen buffer and sets byte-wide plot mode
mov si,x_coord ; si has x-axis in PC screen coord
xor bh,bh
sub bx,32 ; characters in font start at 32
shl bx,1
shl bx,1 ; 8 bytes per char, hence * 8
shl bx,1
mov cx,8 ; 8 bytes (scan lines) to transfer
call gcplot ; call character plot routine
call incx ; move to next char position
pop di
pop es
pop cx
pop bx
ret
gputc endp
putctrl proc near ; CONTROL CHARS = cursor movement
cmp al,FF ; formfeed?
jne putct0 ; ne = no
jmp TEKCLS ; FF clears the screen
putct0: cmp al,BS ; BS? sends (logical) cursor back one
jne putct2 ; ne = no, try next
sub x_coord,8 ; delete 8 dots (move left)
jnc putct1 ; nc = ok
mov x_coord,0 ; limit to left margin
putct1: cmp bscontrol,0 ; non-destructive backspace?
je putctx ; e = yes
push x_coord ; destructive backspace
mov al,spcontrol ; save this
push ax
mov spcontrol,1 ; destructive space
mov al,' ' ; a space to be written
call gputc ; write it
pop ax
mov spcontrol,al ; restore space control
pop x_coord ; restore cursor
ret
putct2: cmp al,TAB ; tabs move forward one char position
jne putct4 ; ne = not a tab
;;; OR X_COORD,7*8
jmp incx ; let incx move cursor right one col
putct4: cmp al,CR ; <CR> means go to beginning of line
jne putct5
mov x_coord,0 ; zero the x coordinate
ret
putct5: cmp al,LF ; <LF> means go down 8 pixels (1 line)
jne putct7 ; ne = not LF
add y_coord,8 ; border managed by outscrn and incx
ret
putct7: cmp al,VT ; <VT> move up screen 1 line (8 pixels)
jne putctx
sub y_coord,8 ; subtract one line (8 pixels)
jnc putctx ; nc = space left
mov y_coord,8 ; else set to top of screen
putctx: ret
putctrl endp
mputc proc near ; MONO put char in AL via Bios
push bx ; updates x_coord,y_coord with
push cx ; new cursor position
push dx
xor ah,ah ; marker for cursor setting not needed
cmp al,' ' ; control code?
jae mputc1 ; ae = no, printable
call putctrl ; do cursor arithmetic
mov ah,1 ; marker to set cursor but no display
mputc1: push ax ; save char and marker
mov cl,3 ; char cell is 8 x 8 dots
mov ax,x_coord ; get resulting cursor PC positions
shr ax,cl
mov dl,al ; column
mov ax,y_coord
sub ax,7 ; minus 7 dots, like other modes
jnc mputc2 ; nc = non-negative
mov ax,7 ; else start at the top
mov y_coord,ax ; here too
mputc2: shr ax,cl
mov dh,al ; row
mov ah,2 ; set cursor to x_coord,y_coord
xor bh,bh ; page 0
int screen
pop ax
or ah,ah ; write a char in al?
jnz mputcx ; nz = no
mov ah,09h ; write char at cursor postion
mov cx,1 ; just one char
xor bh,bh ; page 0
mov bl,gfcol ; foreground coloring
int screen
inc dl ; next column
mov ah,2 ; set real cursor ahead of last char
int screen
call incx ; move logical cursor
mputcx: pop dx
pop cx
pop bx
ret
mputc endp
incx proc near ; move the logical cursor right
mov ax,xmax
add ax,8 ; last column+1
cmp ax,x_coord ; beyond right most column?
jae incx1 ; ae = no
mov x_coord,ax ; set up for wrap
ret
incx1: add x_coord,8 ; shift the (logical) cursor right
ret ; one character cell
incx endp
; Character plot routine. Enter with bx pointing at font array for char
; cx = number of bytes in char font, es:di = screen memory. Worker for gputc.
; ccode: pixbak=plot in backgrd colors, pixfor=foregrd, pixxor=xor with screen
gcplot proc near
mov al,ccode ; save original ccode and fill pattern
mov ah,fill
push ax
or bx,bx ; dealing with "space"?
jnz gcplot1 ; nz = no
cmp spcontrol,0 ; transparent space?
jne gcplot2 ; ne = no, do destructive space
gcplot1:cmp chcontrol,0 ; transparent char writing?
je gcplot3 ; e = yes
gcplot2:mov ccode,pixfor+pixbak ; write both fore and back ground
gcplot3:mov al,font[bx] ; EGA byte plot: get bits from font
push bx
push cx
mov cx,si ; x-axis in PC screen coordinates
and cx,7 ; bit in byte across the screen
ror al,cl ; rotate pattern for gfplot filling
mov cx,8 ; do 8 bits on the line
mov fill,al ; use "fill" as fill pattern
call gfplot ; fill a scan line for cx bits
call pincy ; next scan line (linelen is preset)
pop cx
pop bx
inc bx ; next byte of char pattern
loop gcplot1
pop ax
mov ccode,al ; recover variables
mov fill,ah
ret
gcplot endp
; routines to manipulate ega graphics controller and mode register
; command code in al, value in ah - destroys al and dx
ega_gc proc near ; ega graphics controller
mov dx,3ceh
out dx,al ; output command code
inc dx ; dx is now data port
mov al,ah ; get value to al
out dx,al ; output value
ret
ega_gc endp
ega_md proc near ; ega mode controller
mov dx,3c4h
out dx,al ; output command code
inc dx ; dx is now data port
mov al,ah ; get value to al
out dx,al ; output value
ret
ega_md endp
; Plot eight pixels using an EGA board
; Enter with ES:[DI] pointing to screen address of byte,
; bh has pattern of bits to be set, bl has attributes:
; pixbak = draw in background color, pixfor = draw in foreground color,
; pixor = OR with foreground color, pixxor = XOR with foreground color.
; registers preserved
; Note: this function operates on 8 pixels. One bits in bh select pixels to
; be changed, bl determines which color planes will be affected for every
; selected pixel.
ega_plt proc near
push ax
push dx
mov dx,3ceh ; (ega_gc) unprotect the bit positions
mov al,8 ; command to set bit mask register
out dx,al ; output command code
inc dx ; dx is now data port
mov al,bh ; get pixels to be modified (1's)
out dx,al ; output value (end of ega_gc)
pop dx
mov ah,gfcol ; foreground color bit planes
ega1: test bl,pixfor+pixor ; write foreground or OR?
jnz ega3 ; nz = yes
mov ah,gbcol ; background color bit planes
test bl,pixbak ; write in background coloring?
jnz ega3 ; nz = yes
mov ah,0fh ; xor, touch each bit plane
ega3: mov al,es:[di] ; latch byte
mov es:[di],ah ; merge with untouched bits
pop ax
ret
ega_plt endp
; Presence test for Wyse-700: info in B000h and B800h are supposed to be equal
chkwyse proc near
push es
push ds
mov ax,0b800h ; CGA segment
mov es,ax
mov ax,0b000h ; Mono segment
mov ds,ax
mov ch,byte ptr es:[0] ; CGA seg
mov cl,byte ptr ds:[0] ; Mono seg
push cx ; save original contents
mov byte ptr ds:[0],ch ; copy CGA to Mono
cmp byte ptr ds:[0],ch ; if different then not Wyse
jne chkwys1 ; ne = not Wyse
not byte ptr es:[0] ; change CGA contents
not ch ; and original pattern
cmp ch,byte ptr ds:[0] ; if different then not Wyse
jne chkwys1 ; ne = not Wyse
pop cx
mov byte ptr es:[0],ch ; restore CGA
mov byte ptr ds:[0],cl ; restore Mono
pop ds
pop es
clc
ret
chkwys1:pop cx
mov byte ptr es:[0],ch ; restore CGA
mov byte ptr ds:[0],cl ; restore Mono
pop ds
pop es
stc
ret
chkwyse endp
;
; routine to set Wyse-700 board to graphics mode - 1280 * 800 & cls
;
WYGRAF PROC NEAR
push ax
push bx ; save used registers
push cx
push dx
push di
xor al,al
mov dx,wystoff ; map video memory offset to zero
out dx,al ;
mov dx,wystseg ; map video memory segment to zero
out dx,al ;
mov ax,segwyse ; set es to Wyse start segment
mov es,ax ;
mov al,wybeven ; graph mode - even bank
mov dx,wymode ; Wyse mode control register
out dx,al ; select even bank
cld
xor ax,ax ; zero ax
xor di,di ; start from zero
mov cx,0ffffh ; clear 10000h bytes, whole even bank
rep stosb ; store blanking char in whole screen
mov al,wybodd ; graph mode - odd bank
mov dx,wymode ; select it
out dx,al ;
xor ax,ax ; zero ax
xor di,di ;
mov cx,0ffffh ; clear 10000h bytes, whole odd bank
rep stosb ; store blanking char in whole screen
mov bnkchan, 0 ; assume bank 0
pop di ; restore regs
pop dx
pop cx
pop bx
pop ax
ret
WYGRAF ENDP
; routine to set Hercules card to graphics mode - both pages are enabled
HGRAF PROC NEAR
push ax
push bx ; save used registers
push cx
push si
mov al,grph ; graph mode
lea si,gtable ; requires graphics table
xor bx,bx
mov cx,4000h ; clear 4000h words
test gbcol,7 ; any (light) background color bits?
jz hgraf1 ; z = no, we are ok
dec bx ; light background, set all the bits
hgraf1: call setmd ; and set the mode
pop si
pop cx
pop bx
pop ax
ret
HGRAF ENDP
; set Hercules card to text mode
HTEXT PROC NEAR
push ax
push bx
push cx
push si
mov al,text ; text mode
lea si,ttable ; requires text table
mov bx,0720h ; blank value (space, white on black)
mov cx,2000 ; whole screen to clear (80*25)
call setmd ; set the mode
pop si
pop cx
pop bx
pop ax
ret
HTEXT ENDP
; Hercules mode set - called from HTEXT and HGRAF
SETMD PROC NEAR
push dx
push ax
mov dx,config ; configuration port
mov al,genable ; allow graphics mode to be set
out dx,al
pop ax
push ax
push cx ; save count
mov dx,cntrl ; control port
out dx,al ; set to text or graphics
mov dx,index ; send 12 bytes from table to 6845
mov cx,12 ; number of registers to load
xor ah,ah ; start with register 0 of 6845
cld
setmd1: jmp $+2 ; small pause for hardware
mov al,ah ; ah is counter
out dx,al ; set register
inc dx ; point to data port
lodsb ; get next byte in table
jmp $+2 ; small pause for hardware
out dx,al ; and send to 6845
inc ah ; next register
dec dx ; point to register port
loop setmd1 ; and continue 'til cx=0
pop cx ; recover count
cld
push di
push es
mov ax,segscn ; start of screen
mov es,ax
xor di,di
mov ax,bx ; get blanking character
rep stosw ; store blanking char in whole screen
pop es
pop di
mov dx,cntrl ; now to re-enable screen
pop ax ; get mode
or al,scrn_on ; enable screen
out dx,al
pop dx
ret
SETMD ENDP
teksave proc near ; saves graphics screen from page 0 to page 1
push si
push di
cmp gpage,0 ; only graphics page 0 on display board?
je teksavx ; e = yes, no saving possible here
mov si,segscn ; segment (!) of current screen
cmp graph_mode,ega
je teksav1
cmp graph_mode,monoega
je teksav1
cmp graph_mode,colorega
je teksav1
cmp graph_mode,hercules
je teksav2
jmp short teksavx ; else nothing
teksav1:mov di,segega+800h ; EGA page 1 screen segment
call egasr ; call common save/restore code
jmp short teksavx
teksav2:mov di,seghga+800h ; Hercules page 1 screen segment
call hgasr ; call common save/restore code
teksavx:pop di
pop si
ret
teksave endp
tekrest proc near ; restores graphics screen in page 1 to page 0
push si
push di
cmp gpage,0 ; only graphics page 0 on display board?
jne tekres0 ; ne = no, more so work to do here
call tekcls1 ; else clear the screen to color it
jmp short tekresx ; and exit
tekres0:mov di,segscn ; segment (!) of new graphics screen
cmp graph_mode,ega
je tekres1
cmp graph_mode,monoega
je tekres1
cmp graph_mode,colorega
je tekres1
cmp graph_mode,hercules
je tekres2
jmp short tekresx ; else nothing
tekres1:mov si,segega+800h ; segment of EGA page 1
call egasr ; call common save/restore code
jmp short tekresx
tekres2:mov si,seghga+800h ; segment of Hercules page 1
call hgasr ; call common save/restore code
tekresx:pop di
pop si
ret
tekrest endp
egasr proc near ; common code for Tek ega save/restore ops
push ax
push cx
push dx
mov ax,0f00h ; enable 4 plane set/resets
call ega_gc ; set controller
mov ax,0f01h ; enable Set/Reset register
call ega_gc
mov ax,0f02h ; set color compare register for 4 planes
call ega_gc
mov ax,0905h ; set mode reg: write latches, read mode
call ega_gc
mov ax,0ff02h ; enable all planes
call ega_md
mov cx,ybot ; last scan line
inc cx ; number of scan lines
mov ax,80 ; bytes per scan line
mul cx
mov cx,ax
push es ; save es
push ds ; save ds
mov es,di ; destination, set es to video memory
mov ds,si ; source, set ds to video memory
xor si,si ; clear offset fields
xor di,di
cld ; byte moves for ega adaptor
rep movsb ; copy from page (ds:si) to page (es:di)
pop ds ; recover ds
pop es ; and other registers
xor ax,ax ; disable 4 plane set/resets
call ega_gc ; set controller
mov ax,0001h ; disable Set/Reset register
call ega_gc ; set controller
mov ax,0002h ; disable color compare register
call ega_gc
mov ax,1005h ; set mode reg: write latches, odd/even
call ega_gc
pop dx
pop cx
pop ax
ret
egasr endp
hgasr proc near ; Hercules save restore screen
push cx
mov cx,4000h ; number of words to move
push es ; save es
push ds ; save ds
mov es,di ; destination, set es to video memory
mov ds,si ; source, set ds to video memory
xor si,si ; clear offset fields
xor di,di
cld
rep movsw ; copy from page [si] to page [di]
pop ds ; recover ds
pop es ; and other registers
pop cx
ret
hgasr endp
dump proc FAR ; Write screen as TIFF v5.0 file
push ax
push bx
push cx
push dx
push si
push di
call remcursor ; remove the cursor from the screen
mov si,offset dumpname ; name of dump file
mov di,offset tempname ; destination
push es
push ds
pop es
mov cx,dumplen ; length of dump name
cld
repnz movsb ; copy it, asciiz
pop es
mov ax,offset tempname ; address to ax for unique
call tunique ; get unique name into ax
mov dx,ax ; ds:dx is asciiz filename
xor cx,cx ; normal attributes
mov ah,creat2 ; create the file
int dos
jc dmp2 ; c = failure
dmp1: mov dhandle,ax ; file handle
call dmpdate ; do time stamp
cmp plotptr,offset pltcga ; using CGA style graphics?
jne dmp2 ; ne = no
call cgadmp ; do CGA style dump routine
jmp short dmp3
dmp2: call egadmp
dmp3: mov cursorst,1 ; pretend cursor was on
call remcursor ; restore the cursor to the screen
mov cursorst,1 ; say it is on
pop di
pop si
pop dx
pop cx
pop bx
pop ax
ret
dump endp
; CGA TIFF 5.0 screen-to-file dump routine
cgadmp proc near
push es ; do the bookkeeping math first
mov bps.entval,1 ; bits/sample, mono
mov photo.entval,1 ; mono, one bit after the other
mov word ptr cmap.entcnt,0 ; no palette color map entries
mov ax,xmax ; image width - 8 pixels
add ax,8 ; plus 8, for pixels per line
mov iwidth.entval,ax ; store in directory
mov xresval,ax ; x resolution
mov xresval+2,0 ; high order part
mov ax,ybot ; lines per screen - 1
inc ax ; lines per screen
mov ilength.entval,ax ; image length, scan lines
mov yresval,ax ; y resolution
mov yresval+2,0 ; high order part
mov cx,25 ; try dividing into this many strips
cgadmp5:xor dx,dx ; image pixels
mov ax,yresval ; number of scan lines
div cx ; try dividing into 25 strips,ax=quo
or dx,dx ; did we get null remainder?
loopnz cgadmp5 ; nz = no, try again with fewer strips
inc cx ; inc for dec by loop, cx = # strips
mov word ptr strip.entcnt,cx ; store number of strips
mov word ptr sbc.entcnt,cx ; store number of strip byte counts
mov rps.entval,ax ; rows per strip
push cx
mov cx,iwidth.entval ; dots per line (row)
shr cx,1 ; get bytes/row
shr cx,1
shr cx,1
mul cx ; rows/strip * bytes/row = bytes/strip
pop cx
push cx ; save strip count for loop below
push ds ; ax = bytes per strip
pop es ; es:di to our data segment
mov di,offset stripbc ; where to write strip byte counts
cld
rep stosw ; write ax as bytes/strip, cx times
pop cx
mov dx,ax ; bytes/strip = increment, put here
mov di,offset stripoff ; where we write
mov ax,offset pixdata-offset header ; where first strip starts
cgadmp4:stosw ; write strip file offset
mov word ptr [di],0 ; high order part
add di,2 ; next double word
add ax,dx ; next file strip offset
loop cgadmp4 ; do all strip offsets
; file i/o starts here
mov bx,dhandle ; dump's file handle
mov dx,offset header ; write TIFF header and directory
mov cx,tifflen ; length of header plus directory
mov ah,write2
int dos
jc cgadmp2 ; c = failure
xor di,di ; start at y = top
call psetup ; setup cga and di
mov cx,ybot ; number of scan lines-1
inc cx ; number of scan lines
cgadmp1:push cx
mov cx,iwidth.entval ; dots per line (row)
shr cx,1 ; get bytes/row
shr cx,1
shr cx,1 ; line length, bytes
mov dx,di ; offset in screen buffer
mov bx,dhandle ; file handle
push ds
mov ax,segscn ; screen seg
mov ds,ax
mov ah,write2 ; write directly from screen memory
int dos
pop ds
jc cgadmp2 ; c = failure
call pincy ; next line down, y = y + 1
pop cx
loop cgadmp1 ; do all scan lines
cgadmp2:mov ah,close2 ; close the file
int dos
mov dhandle,-1 ; set handle to unused
pop es
ret
cgadmp endp
; EGA TIFF 5.0 screen-to-file dump routine
egadmp proc near
push es ; do the bookkeeping math first
mov bps.entval,4 ; bits/sample, iRGB
mov photo.entval,3 ; photo interp, palette
mov word ptr cmap.entcnt,3*16 ; palette color map entries
mov ax,xmax ; image width - 8 pixels
add ax,8 ; plus 8, for pixels per line
mov iwidth.entval,ax ; store in directory
mov xresval,ax ; x resolution
mov xresval+2,0 ; high order part
mov ax,ybot ; lines per screen - 1
inc ax ; lines per screen
mov ilength.entval,ax ; image length, scan lines
mov yresval,ax ; y resolution
mov yresval+2,0 ; high order part
mov cx,25 ; try dividing into this many strips
egadmp10:xor dx,dx ; image pixels
mov ax,yresval ; number of scan lines
div cx ; try dividing into 25 strips, ax=quo
or dx,dx ; did we get null remainder?
loopnz egadmp10 ; nz = no, try again with fewer strips
inc cx ; inc for dec by loop, cx = # strips
mov word ptr strip.entcnt,cx ; store number of strips
mov word ptr sbc.entcnt,cx ; store number of strip byte counts
mov rps.entval,ax ; rows per strip
shl ax,1
shl ax,1 ; times 4 bits / pixel
push cx
mov cx,iwidth.entval ; dots per line (row)
shr cx,1 ; get bytes/row
shr cx,1
shr cx,1
mul cx ; rows/strip * bytes/row = bytes/strip
pop cx
push cx ; save strip count for loop below
push ds ; ax = bytes per strip
pop es ; es:di to our data segment
mov di,offset stripbc ; where to write strip byte counts
cld
rep stosw ; write ax as bytes/strip, cx times
pop cx
mov dx,ax ; bytes/strip = increment, put here
mov di,offset stripoff ; where we write
mov ax,offset pixdata-offset header ; where first strip starts
xor bx,bx
egadmp11:stosw ; write strip file offset
mov es:[di],bx ; high order part
add di,2 ; next double word
add ax,dx ; next file strip offset
adc bx,0
loop egadmp11 ; do all strip offsets
; screen to file i/o starts here
mov bx,dhandle ; dump's file handle
mov dx,offset header ; write TIFF header and directory
mov cx,tifflen ; length of header plus directory
mov ah,write2
int dos
jnc egadmp12
jmp egadmp9 ; c = failure
egadmp12:
xor di,di ; start at y = top
call psetup ; setup adapter and es:di
xor di,di
mov bx,offset tempname ; set buffer address
mov cx,ybot ; number of scan lines-1
inc cx ; number of scan lines
egadmp1:push cx ; save scan line counter
mov cx,iwidth.entval ; dots per line (row)
shr cx,1 ; get bytes/row
shr cx,1
shr cx,1 ; 8*dots across the screen (640)
egadmp2:push cx ; save counter of inner loops
mov cx,4 ; number of planes to do
mov word ptr [bx],0 ; clear the four bytes for this loop
mov word ptr [bx+2],0
egadmp3:push cx ; save plane counter
push bx ; don't advance buffer pointer here
mov dx,3ceh ; (ega_gc)
mov al,4 ; command to select read map register
out dx,al ; output command code
inc dx ; dx is now data port
mov al,cl ; do planes 3(I), then 2(R),1(G),0(B)
dec al ; cx is one higher than plane
out dx,al ; output value (end of ega_gc)
mov al,es:[di] ; latch byte
; got 8 bits from a plane
mov cx,4 ; do this for four output bytes
egadmp4:mov ah,[bx] ; eventually iRGB in each nibble
shl al,1 ; get left most pixel bit in plane
jnc egadmp5
or ah,8 ; set high nibble least sig bit
egadmp5:shl al,1 ; odd numbered pixel
rcl ah,1 ; set low nibble least sig bit if c
mov [bx],ah
inc bx ; next byte
loop egadmp4 ; do all four bytes
pop bx
pop cx ; restore plane counter
loop egadmp3 ; do all planes
inc di ; next screen memory address
add bx,4 ; just did four bytes
cmp bx,offset tempname+80 ; at end of 80 bytes?
jb egadmp6 ; b = no
call egadmpw ; write the buffer
mov bx,offset tempname ; reset buffer address
jnc egadmp6 ; nc = success
pop cx ; clean stack
pop cx
jmp egadmp9 ; error
egadmp6:pop cx ; recover bytes per line counter
loop egadmp2 ; next group across scan line
pop cx ; recover scan line counter
loop egadmp1 ; do next scan line
call egadmpw ; flush the buffer for last scan line
egadmp9:mov ah,close2 ; close the file
mov bx,dhandle
int dos
mov dhandle,-1 ; set handle to unused
xor di,di
call psetup
pop es
ret
; local worker
egadmpw:push bx ; write tempbuf from start to [bx-1]
push cx
mov dx,offset tempname ; work buffer
mov cx,bx ; buffer pointer to next free byte
sub cx,dx ; buffer size to write
cmp cx,0
jle egadmpw1 ; le = nothing to write
mov bx,dhandle ; file handle
mov ah,write2 ; write cx bytes from tempname
int dos
jc egadmpw2 ; c = error
cmp ax,cx ; wrote all?
jne egadmpw2 ; ne = no
egadmpw1:clc ; clc
pop cx
pop bx
ret
egadmpw2:stc ; carry set for failure
pop cx
pop bx
ret
egadmp endp
; Worker. Write Kermit version and current date and time in TIFF header
dmpdate proc near
mov di,offset prog+10 ; place for version in prog field
mov ax,version ; Kermit version
call dec2di ; write the version
mov ah,getdate ; DOS date (cx= yyyy, dh= mm, dl= dd)
int dos
mov di,offset dandt ; where to write
mov ax,cx ; get yyyy
push dx
call dec2di ; write to buffer
pop dx
mov byte ptr [di],':'
inc di
mov al,dh ; mm
cmp al,10 ; leading digit?
jae dmpdat1 ; ae = yes
mov byte ptr [di],'0' ; make our own
inc di
dmpdat1:xor ah,ah
push dx
call dec2di
mov byte ptr [di],':'
pop dx
inc di
mov al,dl ; dd
cmp al,10 ; leading digit?
jae dmpdat2 ; ae = yes
mov byte ptr [di],'0' ; make our own
inc di
dmpdat2:xor ah,ah
call dec2di
mov byte ptr [di],' '
inc di
mov ah,gettim ; DOS tod (ch=hh, cl=mm, dh=ss, dl=.s)
int dos
push dx ; save dx
xor ah,ah
mov al,ch ; Hours
cmp al,10 ; leading digit?
jae dmpdat3 ; ae = yes
mov byte ptr [di],'0' ; make our own
inc di
dmpdat3:push cx
call dec2di ; write decimal asciiz to buffer
pop cx
mov byte ptr [di],':'
inc di
xor ah,ah
mov al,cl ; Minutes
cmp al,10 ; leading digit?
jae dmpdat4 ; ae = yes
mov byte ptr [di],'0' ; make our own
inc di
dmpdat4:call dec2di ; write decimal asciiz to buffer
mov byte ptr [di],':'
inc di
pop dx
xor ah,ah
mov al,dh ; Seconds
cmp al,10 ; leading digit?
jae dmpdat5 ; ae = yes
mov byte ptr [di],'0' ; make our own
inc di
dmpdat5:call dec2di ; write decimal asciiz to buffer
inc di
ret
dmpdate endp
; Dispatch table processor. Enter with BX pointing at table of {char count,
; address of action routines, characters}. Jump to matching routine or return.
; Enter with AL holding received Final char.
atdispat proc near
mov cl,[bx] ; get table length from first byte
xor ch,ch
mov di,bx ; main table
add di,3 ; point di at first char in table
push es
push ds
pop es ; use data segment for es:di below
cld ; set direction forward
repne scasb ; find matching character
pop es
je atdisp2 ; e = found a match, get action addr
cmp al,' ' ; control char?
jb atdisp1 ; b = yes
ret ; ignore escape sequence
atdisp1:jmp tekctl ; process control char
atdisp2:sub di,bx ; distance scanned in table
sub di,4 ; skip count byte, address word, inc
shl di,1 ; convert to word index
inc bx ; point to address of action routines
mov bx,[bx] ; get address of action table
jmp word ptr [bx+di] ; dispatch to the routine
atdispat endp
ansich proc near ; insert Pn spaces at and after cursor
mov cx,param ; get Pn
or cx,cx
jnz ansich1 ; got a value
inc cx ; zero means one
ansich1:push x_coord
push y_coord
mov al,spcontrol ; preserve space control
mov tempname,al ; save here
mov spcontrol,1 ; turn on destructive space
and x_coord,not 7 ; modulo 8x8 cells
mov ax,xmax ; start of last cell
sub ax,x_coord ; start of current cell
shr ax,1 ; divide by 8 dots per char
shr ax,1
shr ax,1
cmp ax,cx ; want more spaces than are on line?
jae ansich2 ; ae = no
mov cx,ax ; clip to right margin
jcxz ansich3 ; z = nothing to do
ansich2:push cx
mov al,' ' ; a space
call outscrn ; write to screen
pop cx
loop ansich2 ; do them
ansich3:mov al,tempname ; space control
mov spcontrol,al ; restored
pop x_coord
pop y_coord
call remcursor ; remove text cursor symbol
call setcursor ; draw cursor at new location
ret
ansich endp
; scaled by text screen height
atcuu proc near ; cursor up Pn lines
cmp param,0 ; empty arg?
jne atcuu1 ; got a value
inc param ; zero means one
atcuu1: mov ax,y_coord ; where we are now
add ax,4 ; round up a smidge
mov cl,byte ptr low_rgt+1 ; highest text line
xor ch,ch
mul cx ; proportion
xor dx,dx
mov cx,ybot ; highest scan line
div cx ; end, estimate currren text line
sub ax,param
inc ax ; count lines from 1 again
mov param,ax ; new text row
jmp atcva ; do as absolute
atcuu endp
; scaled by text screen height
atcud proc near ; cursor down Pn lines
cmp param,0 ; get Pn
jne atcud1 ; ne = got a value
inc param ; zero means one
atcud1: mov ax,y_coord ; where we are now
add ax,4 ; round up a smidge
mov cl,byte ptr low_rgt+1 ; highest text line
xor ch,ch
mul cx ; proportion
xor dx,dx
mov cx,ybot ; highest scan line
div cx ; end, estimate currren text line
inc ax ; count lines from 1 again
add param,ax ; new text row
jmp atcva ; do as absolute
atcud endp
atcuf proc near ; cursor forward Pn columns
mov ax,param ; get Pn
or ax,ax
jnz atcuf1 ; got a value
inc ax ; zero means one
atcuf1: shl ax,1 ; times 8 dots per char cell
shl ax,1
shl ax,1 ; Tek columns worth
and x_coord,not 7 ; modulo 8x8 cells
add x_coord,ax ; forward to absolute column
mov ax,xmax
cmp x_coord,ax ; beyond right most cell?
jbe atcuf2 ; be = no
mov x_coord,ax ; limit to right
atcuf2: call remcursor ; remove text cursor symbol
call setcursor ; draw cursor at new location
ret
atcuf endp
atcub proc near ; cursor left/back Pn columns
mov ax,param ; get Pn
or ax,ax
jnz atcub1 ; got a value
inc ax ; zero means one
atcub1: shl ax,1
shl ax,1
shl ax,1 ; times 8 dots per cell
and x_coord,not 7 ; modulo 8x8 cells
mov cx,xmax
cmp x_coord,cx ; beyond last col (wrap pending)?
jbe atcub3 ; be = no
mov x_coord,cx ; set to last col
atcub3: sub x_coord,ax ; back up
jnc atcub2 ; nc = ok
mov x_coord,0 ; stop in column zero
atcub2: call remcursor ; remove text cursor symbol
call setcursor ; draw cursor at new location
ret
atcub endp
atcnl proc near ; do Pn cr/lf's
mov x_coord,0 ; to left margin
jmp atcud ; do the cursor downs
atcnl endp
atcpl proc near ; do Pn cursor ups
jmp atcuu ; do the cursor ups
atcpl endp
; scaled by text screen width
atcha proc near ; cursor to absolute column
and x_coord,not 7 ; modulo 8x8 cells
mov ax,param ; get Pn
or ax,ax
jz atcha1 ; z = zero already
dec param ; count columns from 0
mov ax,xmax ; number of Tek dots/row
mul param ; times columns they want
mov cl,byte ptr low_rgt ; number of last text column
xor ch,ch
xor dx,dx
div cx ; scale to ~80 column screen
cmp ax,xmax ; too far?
jbe atcha1 ; be = no
mov ax,xmax ; right most column
atcha1: mov x_coord,ax
call remcursor ; remove text cursor symbol
call setcursor ; draw cursor at new location
ret
atcha endp
; scaled by text screen height
atcva proc near ; cursor to absolute row
dec param ; count from 0
mov ax,param ; desired text row
or ax,ax ; zero or now -1?
jg atcva1 ; g = no, further down
mov ax,7 ; bottom of top text cell
jmp short atcva2
atcva1: mov ax,ybot
inc ax ; number of scan lines on screen
;;;; and ax,not 7 ; whole 8x8 char cells
mul param ; times row they want
mov cl,byte ptr low_rgt+1 ; number of last text line (0..23)
xor ch,ch
xor dx,dx
div cx ; scale to ~24 line screen
mov cx,ybot
;;;; and cx,not 7 ; whole 8x8 char cells
cmp ax,cx ; too far?
jbe atcva2 ; be = no
mov ax,cx
atcva2: mov y_coord,ax ; go to that line
call remcursor ; remove text cursor symbol
call setcursor ; draw cursor at new location
ret
atcva endp
atcup proc near ; cursor to absolute row, column
call atcva ; process param[0] as absolute row
push param[2] ; column
pop param
jmp atcha ; process param[2] as absolute column
atcup endp
ated proc near ; erase display
mov al,spcontrol ; preserve space control
mov tempname,al ; save here
mov spcontrol,1 ; turn on destructive space
push x_coord
push y_coord ; save cursor
cmp param,0 ; cursor to end of screen?
je ated1 ; e = yes
cmp param,1 ; start of screen to cursor?
je ated3 ; e = yes
cmp param,2 ; entire screen?
je ated5 ; e = yes
ret ; else ignore
ated1: mov param,0 ; cursor to end of this line
call atel ; erase cursor to end of line
add y_coord,8 ; look at next line
mov ax,ybot
cmp y_coord,ax ; are we at the end now?
ja ated6 ; a = yes
mov x_coord,0 ; start of line is here
jmp ated1 ; do through last line
ated3: and y_coord,not 7 ; modulo 8x8 char cells
mov cx,y_coord ; start of screen to cursor
shr cx,1 ; char lines at 8 dots/char
shr cx,1
shr cx,1
dec cx ; omit current line= # whole lines
or cx,cx ; any whole lines?
jle ated3b ; le = no
mov y_coord,7 ; start at the top line
ated3a: push cx
mov param,2 ; entire line
call atel ; erase entire line
add y_coord,8 ; next line
pop cx
loop ated3a
ated3b: mov param,1 ; start of line to cursor
call atel ; erase to cursor on this (last) line
jmp short ated6
ated5: call tekcls ; erase whole screen
ated6: mov al,tempname ; spacing control
mov spcontrol,al
pop y_coord
pop x_coord
call remcursor ; remove last cursor
call setcursor ; set cursor to original position
ret
ated endp
atech proc near ; erase Pn chars from cursor to eol
mov al,spcontrol ; preserve space control
mov tempname,al ; save here
mov spcontrol,1 ; turn on destructive space
push x_coord
push y_coord ; save cursor
mov cx,x_coord
and cx,not 7 ; modulo 8x8 cells
mov ax,xmax
sub ax,cx ; number of chars remaining on line
shr ax,1
shr ax,1
shr ax,1
inc ax ; count cursor cell
mov cx,param ; how many chars to erase
or cx,cx
jz atech1 ; z = zero, use one
inc cx
atech1: cmp ax,cx ; want more than line length?
jae atech2 ; ae = no
mov cx,ax ; clip at right margin
or cx,cx
jle atech3 ; le = nothing to do
atech2: push cx
mov al,' '
call outscrn ; write spaces
pop cx
loop atech2
atech3: mov al,tempname ; spacing control
mov spcontrol,al
pop y_coord
pop x_coord
call remcursor ; remove last cursor
call setcursor ; set cursor to original position
ret
atech endp
atel proc near ; erase on this line
call remcursor ; remove cursor
push x_coord
push y_coord
cmp param,0 ; cursor to end of line?
je atel1 ; e = yes
cmp param,1 ; start of line to cursor?
je atel3 ; e = yes
cmp param,2 ; whole line?
jne atel5 ; ne = no, fail
mov x_coord,0 ; erase entire line
atel1: mov cx,xmax ; cursor to end of line
mov ax,x_coord
and ax,not 7 ; modulo 8x8 cells
sub cx,ax
shr cx,1
shr cx,1
shr cx,1 ; 8 dots/char
inc cx ; count the cursor cell
or cx,cx
jle atel5 ; le = do nothing
mov al,spcontrol ; preserve space control
mov tempname,al ; save here
mov spcontrol,1 ; turn on destructive space
atel2: push cx ; start of line to cursor
mov al,' '
call outscrn
pop cx
loop atel2
mov al,tempname ; space control
mov spcontrol,al ; restored
atel5: pop y_coord
pop x_coord
call remcursor ; remove last cursor
call setcursor ; set cursor to original position
ret
atel3: mov cx,x_coord ; start of line to cursor
shr cx,1
shr cx,1
shr cx,1
inc cx ; count cursor cell
mov x_coord,0 ; go to start of line
jmp atel2 ; do the loops
atel endp
code2 ends
end